开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情
1.找树左下角的值
题目描述
解题思路
迭代法:
本题使用迭代法比较简单,层序遍历这棵树,找到最下面一层的第一个元素就是最左下角的值,层序遍历需要用一个辅助队列来完成。
var findBottomLeftValue = function(root) {
const queue = []
queue.push(root)
const result = []
while(queue.length) {
let size = queue.length;
const tmp = []
while(size--) {
const node = queue.shift() // 出队列
tmp.push(node.val)
node.left&&queue.push(node.left) //入队列 先入先出
node.right&&queue.push(node.right)
}
result.push(tmp)
}
return result.pop().shift() // 最后一层的第一个元素
};
递归法:
本题使用递归法比较复杂,涉及到回溯过程,保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。
1.确认递归参数和返回值。
let result // 全局变量 记录最左下角的值
let maxDep = -1 // 因为本题一定有一个节点,所以最大值定义为-1即可
var traversal = function(node,depth){
}
2.确认递归终止条件
if(node.left==null&&node.right==null) { 左右子树为空则为叶子节点
if(depth > maxDep) {
maxDep = depth
result = node.val // 更新左下角的值和树的深度 最深一层的值就是最左下角的值
}
}
3.单层处理逻辑
if(node.left) {
depth++
traversal(node.left,depth)
depth-- // 回溯 不然下次递归depth会一直增大
}
if(node.right){
depth++
traversal(node.right,depth)
depth-- // 回溯
}
整体代码
var findBottomLeftValue = function(root) {
let result
let maxDep = -1;
var traversal = function(node,depth){
if(node.left==null&&node.right==null){
if(depth>maxDep){
maxDep = depth;
result = node.val
}
}
if(node.left){
depth++
traversal(node.left,depth)
depth--
}
if(node.right){
depth++
traversal(node.right,depth)
depth--
}
// return
}
traversal(root,0)
return result
};
2.路径总和
题目描述
解题思路
本题同样使用递归法,需要注意的是,求路径和需要有返回值
var hasPathSum = function(root, targetSum) {
var getSum = function(node,sum) { // 参数 返回值 true false
if(node.left == null&&node.right==null){
if(sum == targetSum) { // 叶子节点 且和刚好相等 直接返回true
return true
} else {
return false // 否则返回false
}
}
if(node.left) { // 单层逻辑
sum += node.left.val // 这里加的是node.left.val node.val在上层递归已经加上了
if(getSum(node.left,sum)) return true // 回溯
sum -= node.left.val
}
if(node.right){
sum += node.right.val
if(getSum(node.right,sum)) return true // 回溯
sum -= node.right.val
}
return false
}
if(root == null) return false
return getSum(root,root.val)
};
题目描述
解题思路
1.从后续遍历的顺序可以找出树的根节点,中序遍历最后一个元素就是树的根节点
2.再把中序遍历结果从根节点处分开,左边为左子树,右边为右子树
3.再递归把左右子树根据中序再次切割
var buildTree = function(inorder, postorder) {
var traversal = function(inorder, postorder) {
if(postorder.length === 0) {
return null
}
const root = new TreeNode(postorder[postorder.length-1])
const index = inorder.indexOf(root.val); // 从中序遍历找到分割左右子树的索引
root.left = traversal(inorder.slice(0,index),postorder.slice(0,index)) //左中序 左后序 左区间左闭右开
root.right = traversal(inorder.slice(index+1),postorder.slice(index,postorder.length-1)) //右中序 右后续 左闭右开
return root
}
if(!postorder.length||!inorder.length) return null
return traversal(inorder,postorder)
};
理解该题可以顺便把下面一题一起理解:
105. 从前序与中序遍历序列构造二叉树