LeetCode 513.找树左下角的值
题目链接🔗:513.找树左下角的值
解题思路🤔
使用层序遍历,每一层for循环的时候要用一个固定变量len记录循环次数,不能用que.length(因为这个是变化的)
遇到的问题😢
代码实现👨🏻💻
层序遍历
var findBottomLeftValue = function(root) {
let queue = [];
if(root === null) return null;
queue.push(root);
let resNode;
while(queue.length) {
let length = queue.length;
for(let i = 0; i < length; i++) {
let node = queue.shift();
if(i === 0) resNode = node.val;
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
}
return resNode;
};
总结📖
LeetCode 112. 路径总和
题目链接🔗:112. 路径总和
解题思路🤔
-
确定递归函数的参数和返回值
- 参数:二叉树的根节点、计数器(用来计算二叉树的一条边之和是否正好是目标和)
- 返回值:遍历的路线,并不要遍历整棵树,所以递归函数需要返回值,可以用bool类型表示
-
确定终止条件
使用递减,让计数器初始化为目标和,每次减去遍历路径节点上的数值
如果最后count == 0,同时到了叶子节点时说明找到了目标和
如果到了叶子节点,计数器不为0,就是没找到
-
确定单层递归的逻辑
终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。
递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。
遇到的问题😢
代码实现👨🏻💻
递归法
var hasPathSum = function(root, targetSum) {
const traversal = (node, cnt) => {
// 遇到叶子节点,并且计数为0
if (cnt === 0 && !node.left && !node.right) return true;
// 遇到叶子节点而没有找到合适的边(计数不为0),直接返回
if (!node.left && !node.right) return false;
// 左(空节点不遍历).遇到叶子节点返回true,则直接返回true
if (node.left && traversal(node.left, cnt - node.left.val)) return true;
// 右(空节点不遍历)
if (node.right && traversal(node.right, cnt - node.right.val)) return true;
return false;
};
if (!root) return false;
return traversal(root, targetSum - root.val);
};
总结📖
递归法
判断是否需要返回值的三种情况:
- 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(113.路径总和ii)
- 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (236. 二叉树的最近公共祖先)
- 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(112. 路径总和)
LeetCode 106.从中序与后序遍历序列构造二叉树
题目链接🔗:106.从中序与后序遍历序列构造二叉树
解题思路🤔
第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
第五步:切割后序数组,切成后序左数组和后序右数组
第六步:递归处理左区间和右区间
- 切割中序数组:
切割点在后序数组的最后一个元素,就是用这个元素来切割中序数组的,所以必要先切割中序数组。同时要坚持循环不变量。 - 切割后序数组:
- 使用左闭右开时,首先后序数组的最后一个元素指定不能要了,这是切割点 也是 当前二叉树中间节点的元素,已经用了。
- 后序数组没有明确的切割元素来进行左右切割,不像中序数组有明确的切割点,切割点左右分开就可以了。
- 中序数组大小一定是和后序数组的大小相同的
- 中序数组我们都切成了左中序数组和右中序数组了,那么后序数组就可以按照左中序数组的大小来切割,切成左后序数组和右后序数组。
遇到的问题😢
代码实现👨🏻💻
代码实现
var buildTree = function(inorder, postorder) {
if (!inorder.length) return null;
// 从后序遍历的数组中获取中间节点的值, 即数组最后一个值
const rootVal = postorder.pop();
// 获取中间节点在中序遍历中的下标
let rootIndex = inorder.indexOf(rootVal);
// 创建中间节点
const root = new TreeNode(rootVal);
// 创建左节点
root.left = buildTree(inorder.slice(0, rootIndex), postorder.slice(0, rootIndex));
// 创建右节点
root.right = buildTree(inorder.slice(rootIndex + 1), postorder.slice(rootIndex));
return root;
};