leetcode
leetcode 2651 ~ 2700
二叉树的坡度

二叉树的坡度

难度:

标签:

题目描述

Given the root of a binary tree, return the sum of every tree node's tilt.

The tilt of a tree node is the absolute difference between the sum of all left subtree node values and all right subtree node values. If a node does not have a left child, then the sum of the left subtree node values is treated as 0. The rule is similar if the node does not have a right child.

 

Example 1:

Input: root = [1,2,3]
Output: 1
Explanation: 
Tilt of node 2 : |0-0| = 0 (no children)
Tilt of node 3 : |0-0| = 0 (no children)
Tilt of node 1 : |2-3| = 1 (left subtree is just left child, so sum is 2; right subtree is just right child, so sum is 3)
Sum of every tilt : 0 + 0 + 1 = 1

Example 2:

Input: root = [4,2,9,3,5,null,7]
Output: 15
Explanation: 
Tilt of node 3 : |0-0| = 0 (no children)
Tilt of node 5 : |0-0| = 0 (no children)
Tilt of node 7 : |0-0| = 0 (no children)
Tilt of node 2 : |3-5| = 2 (left subtree is just left child, so sum is 3; right subtree is just right child, so sum is 5)
Tilt of node 9 : |0-7| = 7 (no left child, so sum is 0; right subtree is just right child, so sum is 7)
Tilt of node 4 : |(3+5+2)-(9+7)| = |10-16| = 6 (left subtree values are 3, 5, and 2, which sums to 10; right subtree values are 9 and 7, which sums to 16)
Sum of every tilt : 0 + 0 + 0 + 2 + 7 + 6 = 15

Example 3:

Input: root = [21,7,14,1,1,2,2,3,3]
Output: 9

 

Constraints:

  • The number of nodes in the tree is in the range [0, 104].
  • -1000 <= Node.val <= 1000

代码结果

运行时间: 18 ms, 内存: 17.2 MB


/*
 * 思路:
 * 1. 使用递归来计算每个节点的坡度,同时用流的方式来累加总坡度。
 * 2. 使用一个数组来保存总坡度,递归遍历每个节点并计算左右子树的和。
 * 3. 通过流式处理来计算和累加坡度。
 */

import java.util.stream.Stream;

public class Solution {
    public int findTilt(TreeNode root) {
        return Stream.of(new int[1]).mapToInt(result -> calculateSum(root, result)).sum(); // 计算总坡度
    }

    private int calculateSum(TreeNode node, int[] result) {
        if (node == null) {
            return 0; // 空节点返回0
        }
        int leftSum = calculateSum(node.left, result); // 左子树的和
        int rightSum = calculateSum(node.right, result); // 右子树的和
        result[0] += Math.abs(leftSum - rightSum); // 当前节点的坡度累加到总坡度
        return leftSum + rightSum + node.val; // 返回当前子树的总和
    }
}

解释

方法:

题解采用递归方法遍历二叉树的每个节点,并计算每个节点的坡度。函数sumTree是一个递归函数,它计算并返回当前节点及其所有子节点的值之和。在计算过程中,该函数还计算当前节点左右子树的值之和的差的绝对值,并累加到全局变量self.ans中,以计算整棵树的坡度总和。递归的基础情况是当遇到空节点时,返回0,表示该节点的值之和为0。

时间复杂度:

O(n)

空间复杂度:

O(h),其中h是树的高度

代码细节讲解

🦆
在递归函数sumTree中,你是如何确保每个节点的坡度只被计算一次的?
在递归函数sumTree中,每次调用都会处理一个特定的节点,并在该节点上直接计算其坡度。这是通过获取其左右子树的总和,计算这两个数之差的绝对值来实现的。每个节点在递归过程中只被访问一次,因此每个节点的坡度也只被计算一次。这确保了整个树中的每个节点的坡度都准确地被计算了一次,不会重复计算。
🦆
递归函数sumTree返回的是当前节点及其子节点的总和,那么这个返回值是如何在计算坡度时被利用的?
递归函数sumTree返回当前节点及其所有子节点的值的总和。这个返回值通过两个子递归调用(对左子树和右子树)得到,并加上当前节点的值。这个总和不仅用于上层递归调用中父节点的总和计算,更重要的是,使用左右子树的总和(分别为L和R)来计算当前节点的坡度,即`abs(L - R)`。这样,每个节点的坡度都是基于其子树的正确总和计算出来的,从而确保了整棵树的坡度计算的准确性。
🦆
你是如何处理空节点的情况,以防在计算坡度时出现null引用错误?
在递归函数sumTree中,处理空节点的情况是通过检查当前节点是否为null来实现的。如果是空节点(null),函数直接返回0。这种设计确保当递归到达树的底部且没有更多的子节点时,不会尝试访问null节点的属性,从而避免了null引用错误。这也使得空节点对于父节点的坡度计算不会有贡献,因为它们的值总和为0。

相关问题