513. 找树左下角的值
要求: 给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
思路
1.递归法:递归找到左节点但不一定是最大深度的左下角的节点,所以需要遍历时记录下深度,当深度更新时,将存放在res中的左节点的值。
var findBottomLeftValue = function(root) {
//递归法 找到最大深度,记录下每个深度的第一个左节点
let res = 0
let depth = 0, maxDepth = -Infinity //maxDepth需设为最小值,当root只有一个根节点时,
function getDepth(node){
if(node.left == null && node.right == null){
//叶子节点
if(maxDepth < depth){
maxDepth = depth
res = node.val
console.log(node.val, maxDepth, depth)
return
}
}
if(node.left){
depth++
getDepth(node.left)
depth--
}
if(node.right){
depth++
getDepth(node.right)
depth--
}
}
getDepth(root)
return res
};
2.迭代法 本题用迭代法反而更容易,只需要在每一行记录下第一个值,并不要求是左节点。
var findBottomLeftValue = function(root) {
//迭代法
let queue = [root]
let res = 0
while(queue.length){
let size = queue.length
res = queue[0].val
while(size--){
let node = queue.shift()
if(node.left) queue.push(node.left)
if(node.right) queue.push(node.right)
}
}
return res
};
112. 路径总和
要求: 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
思路
递归三部曲:
1.确定递归函数的参数和返回类型 参数:二叉树的根节点和计数器(传入targetSum) 本题只需要搜索出一条符合条件的路径,递归需要返回值,找到符合条件的路径就及时返回; 但下面一题路经总和II中需要搜索完整颗二叉树且不用处理递归返回值,那么递归函数就不需要返回值。
2.确定终止条件
当搜索路径所有节点值相加等于目标和时返回,但这里可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值,当count == 0时,且同时到了叶子节点即node.left == null && node.right == null说明找到了目标和;如果遍历到了叶子节点,count不为0,则返回false。
3.单层递归逻辑
if(node.left) { //左节点
count -= node.left.val
if(getPath(node.left, count)) return true
count += node.left.val //回溯
}
if(node.right){
count -= node.right.val
if(getPath(node.right, count)) return true
count += node.right.val //回溯
}
return false
代码
var hasPathSum = function(root, targetSum) {
function getPath(node, count){
if(node.left == null && node.right == null && count == 0){
return true
}
if(node.left == null && node.right == null){
return false
}
if(node.left) {
count -= node.left.val
if(getPath(node.left, count)) return true
count += node.left.val
}
if(node.right){
count -= node.right.val
if(getPath(node.right, count)) return true
count += node.right.val
}
return false
}
if(root == null ) return false
return getPath(root, targetSum-root.val)
};
113. 路径总和 II
var pathSum = function(root, targetSum) {
let path = [], res =[]
function getPath(node, sum){
if(node.left == null && node.right == null && sum == targetSum){
res.push([...path])
return
}
if(node.left == null && node.right == null){
return
}
if(node.left) {
path.push(node.left.val)
sum += node.left.val
getPath(node.left, sum)
path.pop()
sum -= node.left.val
}
if(node.right){
path.push(node.right.val)
sum += node.right.val
getPath(node.right, sum)
path.pop()
sum -= node.right.val
}
return
}
if(root == null )return res
path.push(root.val)
getPath(root, root.val)
return res
};
106. 从中序与后序遍历序列构造二叉树
要求:给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这棵 二叉树 。
思路
var buildTree = function(inorder, postorder) {
if(inorder.length == 0 || postorder.length == 0) return null
let rootValue = postorder[postorder.length - 1] //后序数组的最后一个元素是中间节点
const root = new TreeNode(rootValue)
let index = inorder.indexOf(rootValue) //找到后序数组的最后一个元素在中序数组的位置,作为切割点
//切割中序数组和后序数组,区间为左闭右开,slice方法
root.left = buildTree(inorder.slice(0, index), postorder.slice(0, index))
root.right = buildTree(inorder.slice(index+1), postorder.slice(index, postorder.length-1))
return root
};
105. 从前序与中序遍历序列构造二叉树
要求:给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
思路
var buildTree = function(preorder, inorder) {
if(inorder.length == 0 || preorder.length == 0) return null
let rootValue = preorder[0]
const root = new TreeNode(rootValue)
let index = inorder.indexOf(rootValue)
root.left = buildTree(preorder.slice(1, index+1), inorder.slice(0, index))
root.right = buildTree(preorder.slice(index+1), inorder.slice(index+1))
return root
};