【算法三道】二叉树的最近公共祖先&&路径总和 一 二

236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

在这里插入图片描述
这个题目先看懂官方题解
就是有两种可能

  • 一种就是如果当前节点就是最近的公共节点,那么这个节点的右子树和左子树分别都有一个参数(q|p)

  • 一种就是当前节点就是参数中的一个,假设是q,那么存在的情况就是,另一个p可能存在q节点的左子树也可能存在这个节点的右子树上
    然后我们需要用到的方法就是递归啦

左右节点记录一下

 const lson = dfs(root.left, p, q)
 const rson = dfs(root.right, p, q)

整个的判断一遍

if ((lson && rson) || (root.val === p.val || root.val === q.val) && (lson || rson)) {
            ans = root;
        }
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
var lowestCommonAncestor = function(root, p, q) {
    let ans;
    const dfs = (root, p, q) => {
        if (root === null) return false;
        const lson = dfs(root.left, p, q)
        const rson = dfs(root.right, p, q)
        if ((lson && rson) || (root.val === p.val || root.val === q.val) && (lson || rson)) {
            ans = root;
        }
        return lson || rson || (root.val === p.val || root.val === q.val)
    }
    dfs(root, p, q)
    return ans;
};

下面有两道路径总和的题,一道题是只需要判断是否存在一条路径的总和为targetSum 还有一道题是需要将所有满足和的路径打印出来

都是用的递归

但这里有需要注意的一个就是,递归什么时候需要返回值什么时候不需要。

如果是找某条满足的路径就可以,就需要返回值,true或者false来判断是否需要继续递归下去

如果是整个树都需要递归,那么就不需要返回值

112. 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum ,判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。

叶子节点 是指没有子节点的节点。

/**
 * @param {TreeNode} root
 * @param {number} targetSum
 * @return {boolean}
 */
var hasPathSum = function(root, targetSum) {
    if (root === null) return false
    if (root.right === null && root.left === null) {
        return targetSum - root.val == 0
    }
    return hasPathSum(root.left, targetSum- root.val) || hasPathSum(root.right, targetSum - root.val)
};

113. 路径总和 II

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

  • 到叶子节点了,刚好也找到一条路径了
  • 到叶子节点了,但是还没有找到
  • node.left
 if(root.left) {
       path.push(root.left.val)
       dfs(root.left,cnt - root.left.val,path)
       path.pop()
  }
  • node.right
 if(root.right) {
     path.push(root.right.val)
     dfs(root.right,cnt - root.right.val,path)
     path.pop()
}

path.pop()是回溯, 如果到了某条叶子节点的值还没达到所需要的值。就向上回溯

/**
 * @param {TreeNode} root
 * @param {number} targetSum
 * @return {number[][]}
 */
var pathSum = function(root, targetSum) {
    let res = [];
    const dfs = (root,cnt,path) => {
		// 1
        if (cnt === 0 && !root.right && !root.left) {
             res.push([...path])
             return
        }
        // 2
        if (!root.right && !root.left) {
            return ;
        }
        // 3
        if(root.left) {
            path.push(root.left.val)
            dfs(root.left,cnt - root.left.val,path)
            path.pop()
        }
        // 4
        if(root.right) {
            path.push(root.right.val)
            dfs(root.right,cnt - root.right.val,path)
            path.pop()
        }
        return
    }
    if (root === null) return []
    dfs(root,targetSum - root.val,[root.val])
    return res
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值