[路飞]_程序员必刷力扣题: 863. 二叉树中所有距离为 K 的结点

301 阅读1分钟

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

863. 二叉树中所有距离为 K 的结点

给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 k 。

返回到目标结点 target 距离为 k 的所有结点的值的列表。 答案可以以 任何顺序 返回

示例1: image.png

输入:root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, k = 2
输出:[7,4,1]
解释:所求结点为与目标结点(值为 5)距离为 2 的结点,值分别为 7,4,以及 1

示例2:

输入: root = [1], target = 1, k = 3
输出: []

提示:

  • 节点数在 [1, 500] 范围内
  • 0 <= Node.val <= 500
  • Node.val 中所有值 不同
  • 目标结点 target 是树上的结点。
  • 0 <= k <= 1000

从目标节点上下递归

思路 由题意可知,给定我们一棵二叉树,并且指定了一个目标节点

如示例1中的target为5,并不是说target是数字5,而是说target是值为5的这个节点,是一个对象。

接着给了一个范围k,收集所有距离traget为k的值,距离我们可以理解为两节点之间相连的线,两个节点之间为1,因此就是数k条线对应的那个节点的值

这里我们从目标节点target出发,向上和向下查找

具体实现:

  • 首先深度优先遍历整个二叉树,同时处理所有节点,给他们一个prev 指向他们的父节点
  • 处理完毕声明两个查找函数
    • 向下查找每次判断当前距离n是否等于k,等于则结束递归,否则递归查找left和right子节点,同时n+1
    • 向上查找,就是从prev开始找,找到目标节点后还要继续递归爷爷节点,以及父节点的另外一个子节点,距离n+1
    • 当n===k时将当前节点root存放到res中

最后返回res即可

var distanceK = function (root, target, k) {
    var stack = [root]
    var res = []
    while (stack.length) {
        var item = stack.pop()
        // 处理左右
        var left = item.left
        var right = item.right
        if (left) {
            left.prev = item
            stack.push(left)
        }
        if (right) {
            right.prev = item
            stack.push(right)
        }
    }
    // 向下查找
    function findDown(root, n) {
        if (!root) return
        if (n === k) {
            res.push(root.val)
            return
        }
        findDown(root.left, n + 1)
        findDown(root.right, n + 1)
    }
    // 向上查找
    function findUp(root, n, prev) {
        if (!root) return
        if (n === k) {
            res.push(root.val)
            return
        }
        if (n > k) return
        // 向下
        if (root.left && root.left.val === prev) {
            findDown(root.right, n + 1)
        }
        if (root.right && root.right.val === prev) {
            findDown(root.left, n + 1)
        }
        // 向上
        findUp(root.prev, n + 1, root.val)

    }
    // 处理起点
    if (k === 0) {
        return [target.val]
    } else {
        // 向下查找
        findDown(target.left, 1)
        findDown(target.right, 1)
        // 向上查找
        findUp(target.prev, 1, target.val)
    }
    return res
};