【未完成题目(层序遍历题目)】637.二叉树的层平均值、429.N叉树的层序遍历、515.在每个树行中找最大值、116.填充每个节点的下一个右侧节点指针、117.填充每个节点的下一个右侧节点指针II、104.二叉树的最大深度、111.二叉树的最小深度(共七道)。
层序遍历 — 102.二叉树的层序遍历
【思路】层序遍历相当于图论中的广度优先搜索,首先思考如何保存每一层的节点,因为要先进先出(先遍历左子树,并且要返回的顺序也是从左往右),想到要用队列的结构来实现,保存一层的节点并记录节点个数。再依次弹出节点,nums
记录节点,遍历节点的左右子树并把子节点加入到队列中,再把每一层的 nums
记录到最终的二维数组 res
中,循环直至节点为空。
var levelOrder = function(root) {
let res = [], queue = [root];
if (root === null) return res;
while (queue.length) {
let len = queue.length;
let nums = []; //注意 nums 一定要定义在第一层 while 循环里
while(len--) {
let node = queue.shift();
if (node !== null) nums.push(node.val);
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
res.push(nums);
}
return res;
};
层序遍历 — 107.二叉树的层次遍历II(返回二叉树自底向上的层序遍历)
【思路】返回自底向上的层序遍历遍历就相当于从根节点层序遍历的反转数组。
var levelOrderBottom = function(root) {
if (!root) return [];
let queue = [root], res = [];
while (queue.length) {
let len = queue.length, curLevel = [];
while (len--) {
let node = queue.shift();
curLevel.push(node.val);
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
res.unshift(curLevel); // 倒序添加数组比最后翻转数组更高效,减少运算时间
}
return res;
};
层序遍历 — 199.二叉树的右视图
【思路】先开始考虑了 n 种情况:
1. 首选的是每层右子树的右子树
2. 当右子树的右子树为空时,选择右子树的左子树
3. 当右子树的左子树为空时,选择左子树的右子树
4. 当左子树的右子树为空时,选择左子树的左子树
开始写的时候发现,虽然想清楚了条件,但是无法判断遍历左子树时右子树是否为空,也就无法确定到底要不要判断左子树,甚至想到了加一个 tag 开关来记录右子树是否为空,从而确定是否判断左子树。
看了题解才知道规律:每一层添加的是最右边的元素,也就是层序遍历时每一层的最后一个元素。这样清楚的知道了要选择的元素的特征,就正常层序遍历二叉树,每当循环到队列的长度为 0 时,记录当时的节点即可。
var rightSideView = function(root) {
if (!root) return [];
let res = [], queue = [root];
while (queue.length) {
let len = queue.length;
while (len--) {
let node = queue.shift();
if (len === 0) res.push(node.val); // 长度为 0 时,证明遍历到了每层的最后一个元素正是我们要的元素
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
}
return res;
};
226.翻转二叉树
【思路】递归三部曲!
【未完成】迭代解法(广度和深度两种)
var invertTree = function(root) { // 1. 确定参数
if (!root) return null; // 2. 确定终止条件
// 3. 确定单次执行逻辑:交换左右子节点
let leftNode = root.left;
root.left = invertTree(root.right);
root.right = invertTree(leftNode);
return root; // 1. 确定返回值
};
【未完成】迭代解法
var isSymmetric = function(root) {
const compare = (leftNode, rightNode) => {
// 确定终止条件:节点为空或者值不相等的情况
if (leftNode === null && rightNode !== null) return false
else if (leftNode !== null && rightNode === null) return false
else if (leftNode === null && rightNode === null) return true
else if (leftNode.val !== rightNode.val) return false;
// 单次循环执行逻辑
let outside = compare(leftNode.left, rightNode.right);
let inside = compare(leftNode.right, rightNode.left);
return outside && inside; // 确定返回值
}
return compare(root.left, root.right);
};
参考代码随想录:https://www.programmercarl.com/