解法一:
1.算法思想:
递归,根据【坡度】的定义,可以直接写出对应的递归实现。
2.代码
时间复杂度:每个节点被访问的次数与其所在深度有关。复杂度为 O(n^2)O(n 2 )
空间复杂度:忽略递归来带的额外空间消耗。复杂度为O(1)O(1)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int findTilt(TreeNode root){
if (root == null) return 0;
return findTilt(root.left) + findTilt(root.right) + Math.abs(getSum(root.left) - getSum(root.right));
}
int getSum(TreeNode root){
if (root == null) return 0;
return getSum(root.left) + getSum(root.right) + root.val;
}
}
解法二:优化:
上述解法之所以为 O(n^2)的时间复杂度,是因为我们将「计算子树坡度」和「计算子树权值和」两个操作分开进行。
事实上,我们可以在计算子树权值和的时候将坡度进行累加,从而将复杂度降为 O(n)O(n)。
1.算法步骤:
2.代码
时间复杂度:O(n),其中 nn 为二叉树中结点总数。我们需要遍历每一个结点。
空间复杂度:O(n)。在最坏情况下, 当树为线性二叉树(即所有结点都只有左子结点或没有结点)时,树的高度为 n -1,在递归时我们需要存储 n 个结点。
class Solution {
int ans = 0;
public int dfs(TreeNode node){
if (node == null){
return 0;
}
int sumLeft = dfs(node.left);
int sumRight = dfs(node.right);
ans += Math.abs(sumLeft - sumRight);
return sumLeft + sumRight + node.val;
}
public int findTilt(TreeNode root){
dfs(root);
return ans;
}
}