-
104.二叉树的最大深度
【思路】此题用后序遍历求解最简单。因为子节点到根节点的高度就是二叉树的最大深度。计算子节点的高度,再把高度返回给父节点。如此往复,就可以得到根节点的左右子树的高度,比较后取较大值 + 1 即是最大深度。
层级遍历求最大深度时,每次重新计算队列的长度时,即为遍历新的一层的开始,所以取到队列长度之后depth
自增 1 就是二叉树的最大深度。// 递归 var maxDepth = function(root) { // 二叉树根节点的高度就是二叉树的最大深度 const getDepth = node => { if (!node) return 0; let leftDepth = getDepth(node.left); let rightDepth = getDepth(node.right); return Math.max(leftDepth, rightDepth) + 1; } return getDepth(root); }; // 层级遍历: const maxDepth = root => { if (!root) return 0; let queue = [root], depth = 0; while (queue.length) { let size = queue.length; depth++; while (size--) { let node = queue.shift(); node.left && queue.push(node.left); node.right && queue.push(node.right); } } return depth; }
-
559. n叉树的最大深度
【思路】N 叉树不能用左右子节点的方法遍历,只有 children 节点。所以遍历二叉树用 for 循环,每次遍历一个根节点到子节点的距离,比较现在的根节点到子节点的距离和上一次距离的深度,取每次的最大值,最后得到的 depth 即为最大深度。
N 叉树层序遍历方法同二叉树的层序遍历方法。// 递归法 var maxDepth = function(root) { if(!root) return 0 let depth = 0 for(let node of root.children) { depth = Math.max(depth, maxDepth(node)) } return depth + 1 } // 迭代解法: const maxDepth = root => { if (!root) return 0; let queue = [root], count = 0; while (queue.length) { let size = queue.length; count++; // 每重新记录一次队列长度,证明又是新的一层,记录层数 while (size--) { let node = queue.shift(); for (let item of node.children) { item && queue.push(item); } } } return count; }
-
111.二叉树的最小深度
【思路】求二叉树最小深度时,不能像求最大深度一样,直接比较根节点的左右子树深度,因为会存在可能一遍子树为 NULL 的情况,即没有左子树 or 没有右子树。所以要分情况讨论返回的值是什么:- 左子树为空,右子树不为空:返回右子树的递归结果;
- 左子树不为空,右子树为空:返沪左子树递归结果;
- 左右子树都为空:返回 1(即只有根节点);
- 根节点为空:返回 0;
- 比较左右子树的深度返回较小值
【层序遍历求解】最小深度的特点是遇到第一个左右节点都为 null 的子节点就直接返回深度。
// 递归 var minDepth = function(root) { const getDepth = node => { if (!node) return 0; // 二叉树为空 if (!node.left && !node.right) return 1; // 只有根节点 if (!node.left) return getDepth(node.right) + 1; // 没有左子树,只遍历右子树即可 if (!node.right) return getDepth(node.left) + 1; // 没有右子树,只遍历左子树即可 return Math.min(getDepth(node.left), getDepth(node.right)) + 1; // 左右子树都有的情况下返回最小的高度 } return getDepth(root); }; // 迭代法: const minDepth = root => { if (!root) return 0; let queue = [root], count = 0; while (true) { let size = queue.length; count++; while (size--) { let node = queue.shift(); if (!node.left && !node.right) return count; // 没有左右节点就证明此时的 node 节点为子节点 node.left && queue.push(node.left); node.right && queue.push(node.right); } } }
-
222.完全二叉树的节点个数
【思路】- 利用满二叉树性质求解:满二叉树的节点个数计算公式是 2<<k + 1,而满二叉树一定是完全二叉树。所以我们可以先判断是否为满二叉树,是的话用公式求解,否则正常递归。如何判断根节点的子树是满二叉树呢?完全二叉树的特点是最后一层节点必须是从左至右顺序,中间不能有空节点,而满二叉树是一个节点必须左右子节点全有或者全没有(如下图)。
- 递归解法:正常遍历所有节点计数。
- 层级遍历:队列每次循环的长度就是每一层节点的个数,累加队列长度
size
即可得到总节点个数。
// 利用满二叉树性质
var countNodes = function(root) {
// 考虑两种情况:子树是否是满二叉树
const getCounts = node => {
if (!node) return 0;
let leftNode = node.left, rightNode = node.right, leftCount = 0, rightCount = 0;
while (leftNode) {
leftNode = leftNode.left;
leftCount++;
}
while (rightNode) {
rightNode = rightNode.right;
rightCount++;
}
if (leftCount === rightCount) return Math.pow(2,leftCount + 1) - 1;; // 满二叉树直接返回满二叉树计算节点公式
return getCounts(node.left) + getCounts(node.right) + 1;
}
return getCounts(root);
};
// 递归解法
const countNodes = root => {
if (!root) return 0;
let leftDepth = countNodes(root.left);
let rightDepth = countNodes(root.right);
return leftDepth + rightDepth + 1;
}
// 层级遍历:
const countNodes = root => {
if (!root) return 0;
let queue = [root], count = 0;
while (queue.length) {
let size = queue.length;
count += size;
while (size--) {
let node = queue.shift();
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
}
return count;
}
参考代码随想录:https://www.programmercarl.com/