Reputation: 978
I'm working on the Leetcode problem 110. Balanced Binary Tree and I'm confused on how the subtree values are getting populated when doing recursion. After looking at a few solutions, here's the code I have in Javascript:
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {boolean}
*/
var isBalanced = function(root) {
return treeHeight(root) !== -1;
};
function treeHeight(root){
if(!root) return 0;
const leftSubTree = treeHeight(root.left);
const rightSubTree = treeHeight(root.right);
if(leftSubTree === -1 || rightSubTree === -1) return -1; // how can recursion lead to either subtree being -1? At this point I don't know how this can be true other than "that's just how recursion works"
if(Math.abs(leftSubTree - rightSubTree) > 1) return -1; // how are the values of either subtree even obtained here?
return Math.max(leftSubTree, rightSubTree) + 1; // same as the previous question. how do either subtree even get values?
}
I'm trying to understand the following lines:
if(leftSubTree === -1 || rightSubTree === -1) return -1; // how can recursion lead to either subtree being -1? At this point I don't know how this can be true other than "that's just how recursion works"
if(Math.abs(leftSubTree - rightSubTree) > 1) return -1; // how are the values of either subtree even obtained here?
return Math.max(leftSubTree, rightSubTree) + 1; // same as the previous question. how do either subtree even get values?
I get that the recursion will traverse down the tree on the left side and the rightside. I don't get how through recursion, the subtrees values are getting computed. Can someone explain it please?
Upvotes: 0
Views: 53
Reputation: 4754
I drew this diagram that may help you visualize. When the recursion unfolds, the values passed to parent are underlined in red color. Each node will check the difference of the values reported by its left and right child. If at any node, the diff is > 1, it is not balanced.
Also, at each node, it takes the max of the values reported by left and right child, adds 1 to it (for current level) and sends to its parent.
The left tree is balanced, and the right is not.
Upvotes: 1
Reputation: 780974
Suppose you have a simple tree like:
const tree = {
val: 1,
left: null,
right: {
val: 2,
left: null,
right: null
}
}
When you call treeHeight(tree)
, you get two recursive calls: treeHeight(tree.left)
and treeHeight(tree.right)
.
Since tree.left
is null
, treeHeight(tree.left)
returns 0
, so leftSubtree == 0
.
tree.right
is not null
, so it recurses again, calling treeHeight(tree.right.left
and treeHeight(tree.right.right)
. Since both of these are null
, both return values are 0
, so in this call, leftSubtree == 0
and rightSubtree == 0
. Math.abs(leftSubTree - rightSubTree) == 0
, so it returns Math.max(leftSubtree, rightSubtree) + 1
. Since Math.max(0, 0)
is 0
, this returns 1
.
So in the original call, we now have rightSubtree == 1
. Math.abs(leftSubTree - rightSubTree) > 1) == 1
, so the condition Math.abs(leftSubTree - rightSubTree) > 1)
fails. We go to the else
block and return Math.max(leftSubtree, rightSubtree) + 1
. This returns 2
.
Upvotes: 0
Reputation: 350252
The base case is this:
if(!root) return 0;
So we know how the function could return 0.
The next case to look at is this one:
return Math.max(leftSubTree, rightSubTree) + 1;
We know from the base case that both leftSubTree
and rightSubTree
could be 0 (since they represent a return value from a recursive call), and so we then have a case here where 1 is returned. So now we have seen that either 0 or 1 could be returned.
But then this return
could also get a maximum that is 1, and so return 2! And so any positive integer becomes a possible return value.
Now look at this statement:
if(Math.abs(leftSubTree - rightSubTree) > 1) return -1;
As we saw that leftSubTree
and rightSubTree
could be any unsigned integer (since they are the values returned by a recursive call), the absolute difference can be any unsigned integer, and so there can be cases where this condition is true. So now we have a first case where the returned value is -1 (which here means: "it is not balanced").
The only statement that remains to be explained:
if(leftSubTree === -1 || rightSubTree === -1) return -1;
In the previous case we saw that indeed a recursive call can return -1. So here it says that if either subtree is not balanced then this tree is not balanced either.
Upvotes: 0
Reputation: 19485
few things to note:
+1
.1
or less.treeHeight
is confusing. should be called balancedTreeHeightOrMinusOne
so a tree is balanced if balancedTreeHeightOrMinusOne
is not -1; it is calculated by checking (recursively) the balancedTreeHeightOrMinusOne
of its children. if the diff between them is too big then return -1 for this is not balanced. Otherwise return the height of it's tallest children plus one.
Upvotes: 0