LeetCode刷题日记之二叉树的路径和

80 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情
1.找树左下角的值

题目描述

image.png

解题思路

迭代法:
本题使用迭代法比较简单,层序遍历这棵树,找到最下面一层的第一个元素就是最左下角的值,层序遍历需要用一个辅助队列来完成。

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.路径总和

题目描述

image.png

image.png

解题思路

本题同样使用递归法,需要注意的是,求路径和需要有返回值

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

3.从中序与后序遍历序列构造二叉树

题目描述

image.png

解题思路

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. 从前序与中序遍历序列构造二叉树