二叉搜索树最近节点查询

51 阅读2分钟

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

题目要求

给你一个 二叉搜索树 的根节点 root ,和一个由正整数组成、长度为 n 的数组 queries 。

请你找出一个长度为 n 的 二维 答案数组 answer ,其中 answer[i] = [mini, maxi] :

  • mini 是树中小于等于 queries[i] 的 最大值 。如果不存在这样的值,则使用 -1 代替。
  • maxi 是树中大于等于 queries[i] 的 最小值 。如果不存在这样的值,则使用 -1 代替。

返回数组 answer 。

 

示例 1 :

输入: root = [6,2,13,1,4,9,15,null,null,null,null,null,null,14], queries = [2,5,16]
输出: [[2,2],[4,6],[15,-1]]
解释: 按下面的描述找出并返回查询的答案:
- 树中小于等于 2 的最大值是 2 ,且大于等于 2 的最小值也是 2 。所以第一个查询的答案是 [2,2] 。
- 树中小于等于 5 的最大值是 4 ,且大于等于 5 的最小值是 6 。所以第二个查询的答案是 [4,6] 。
- 树中小于等于 16 的最大值是 15 ,且大于等于 16 的最小值不存在。所以第三个查询的答案是 [15,-1]

示例 2 :

输入: root = [4,null,9], queries = [3]
输出: [[-1,4]]
解释: 树中不存在小于等于 3 的最大值,且大于等于 3 的最小值是 4 。所以查询的答案是 [-1,4] 。

 

提示:

  • 树中节点的数目在范围 [2, 10^5] 内
  • 1 <= Node.val <= 10^6
  • n == queries.length
  • 1 <= n <= 10^5
  • 1 <= queries[i] <= 10^6

思路分析

题目会给我们一个二叉树,并给出一个查询数组,我们需要根据数组里每一个元素从二叉树中找出两个节点,这两个节点的值需要满足以下条件:answer[i] = [mini, maxi] :

  • mini 是树中小于等于 queries[i] 的 最大值 。如果不存在这样的值,则使用 -1 代替。
  • maxi 是树中大于等于 queries[i] 的 最小值 。如果不存在这样的值,则使用 -1 代替。

1、获取二叉树中所有节点的值

所以我们可以先将二叉树中的所有节点遍历保存起来,这里遍历的方法可以是多种,这里我使用的是先序遍历来获取二叉树中所有的节点值。

let arr = [];
const dfs = (r)=>{
    if(!r) return;
    arr.push(r.val);
    dfs(r.left);
    dfs(r.right);
}
dfs(root);

2、对获取到的节点进行排序

获取到二叉树的所有节点之后,我们可以先将节点列表进行排序,方便我们后面查找满足条件的答案。

arr = arr.sort((a,b)=>{
    return a - b;
});

3、二分法查找答案

节点列表排序后,我们可以直接通过二分法来进行搜索,找到满足条件的答案。

const querie = (num)=>{
    let l = 0,r = arr.length - 1;
    while(l < r){
       let m = (l + r) >> 1;
       if(arr[m] == num) return m;
       if(arr[m] > num) r = m;
       else l = m + 1;
    }
    return l;
};
for(let i = 0; i < queries.length; i++){
    let n = querie(queries[i]);
    let r = [];
    if(arr[n] == queries[i]) r = [arr[n],arr[n]];
    else{
        if(arr[n] > queries[i]){
            r = [arr[n - 1] || (- 1),arr[n] || (- 1)];
        }else{
            r = [arr[n] || (-1),arr[n + 1] || (- 1)];
        }
    }
    res.push(r);
}

AC代码

完整AC代码如下:

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number[]} queries
 * @return {number[][]}
 */
var closestNodes = function(root, queries) {
    let arr = [];
    const dfs = (r)=>{
        if(!r) return;
        arr.push(r.val);
        dfs(r.left);
        dfs(r.right);
    }
    dfs(root);
    arr = arr.sort((a,b)=>{
        return a - b;
    });
    let res = [];
    const querie = (num)=>{
        let l = 0,r = arr.length - 1;
        while(l < r){
           let m = (l + r) >> 1;
           if(arr[m] == num) return m;
           if(arr[m] > num) r = m;
           else l = m + 1;
        }
        return l;
    };
    for(let i = 0; i < queries.length; i++){
        let n = querie(queries[i]);
        let r = [];
        if(arr[n] == queries[i]) r = [arr[n],arr[n]];
        else{
            if(arr[n] > queries[i]){
                r = [arr[n - 1] || (- 1),arr[n] || (- 1)];
            }else{
                r = [arr[n] || (-1),arr[n + 1] || (- 1)];
            }
        }
        res.push(r);
    }
    return res;
};

说在最后

本人为算法业余爱好者,如果上面分享有错误的地方,欢迎指出,感激不尽。