代码随想录算法训练营Day 18|513. 找树左下角的值、112. 路径总和、106. 从中序与后序遍历序列构造二叉树

52 阅读3分钟

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 是同一棵树的后序遍历,请你构造并返回这棵 二叉树 。

思路

image.png

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
};