【路飞】算法与数据结构-二叉树中所有距离为 K 的结点

122 阅读2分钟

不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。

LeetCode:原题地址

题目要求

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

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

示例 1:

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

示例 2:

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

思路

  • 设置一个窗口,使得 total - sum === x
  • 其中 total 就是数组的总和,sum 就是窗口里的值的和;
  • 这样移除的值就刚好等于 x 了 在这么多情况下,我们维护一个窗口的长度最大的时候,那么移除的元素就越少,也就是对应的操作数最少
/**
 * @param {number[]} weights
 * @param {number} D
 * @return {number}
 */
var shipWithinDays = function (weights, days) {
    // 设置二分边界
    // 左边界为包裹中最重的重量,确保一定能把所有包裹运送过去
    // 右边界为所有包裹的重量和,一天内便可将所有包裹运送过去
    const sum = weights.reduce((a, b) => a + b)
    let left = Math.max(...weights), right = sum
    // 进行二分查找
    while (left < right) {
        // 选取左右边界的中点
        const mid = (left + right) >> 1
        // 进行计数,求取如果最大运载重量为mid的话,需要多少天来运送所有包裹
        // count为天数,temp为当天运载的重量和
        let count = 1, temp = 0
        // 遍历所有包裹
        for (let weight of weights) {
            temp += weight
            // 如果当前重量超出最大运载重量,便将计数加一,并把当前的重量加到新的一天中
            if (temp > mid) {
                count++
                temp = weight
            }
        }
        // 如果需要的天数超过了days,便把左边界移动到mid+1,否则便将右边界移动到mid
        if (count > days) {
            left = mid + 1
        } else {
            right = mid
        }
    }
    // 退出while循环时left和right是相等的,同时也是我们所求的最低运载能力
    return left
};