开启掘金成长之旅!这是我参与「掘金日新计划 · 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^6n == queries.length1 <= n <= 10^51 <= 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;
};
说在最后
本人为算法业余爱好者,如果上面分享有错误的地方,欢迎指出,感激不尽。