题目描述
给你一个 二叉搜索树 的根节点 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] 。来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/closest-nodes-queries-in-a-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
首先需要通过深度优先搜素把二叉排序树中结点的值依次存入列表ls中,按照左根右的顺序深度优先搜素会得到一个有序的列表
接下来的每次查询操作只需要用二分查找在ls中找x,如果x在ls中出现了,则min=max=x本身,如果x未在ls中出现,最后while循环结束时,left对应的下标就是该次查找x应该在ls中插入的位置,那么min=ls[left-1],max=ls[left],那么就需要判断当前的left是否为0、len(ls),因为当left==0时,前面就不存在比它小的元素,需要返回[-1,ls[left]],如果left==len(ls),就说明后面不存在比它大的元素,需要返回[ls[left-1],-1],除了以上两点边界情况,其他的都可以直接返回[ls[left-1],ls[left]]
注:设置一个标记flag,初始时为true,如果当前查询x存在ls中直接将[x,x]插入ans后,后序就不需要再次判断left位置情况了,所以那些通过break出来的flag会被置为false,外层for循环判断后直接continue进行下一次的查询。
代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def closestNodes(self, root: Optional[TreeNode], queries: List[int]) -> List[List[int]]:
ls=[]
ans=[]
def dfs(root):
if root.left:
dfs(root.left)
ls.append(root.val)
if root.right:
dfs(root.right)
return
dfs(root)
for x in queries:
left,right=0,len(ls)-1
flag=True
while left<=right:
mid=(left+right)//2
if ls[mid]>x:
right=mid-1
elif ls[mid]<x:
left=mid+1
else:
ans.append([x,x])
flag=False
break
if not flag:
continue
if left==len(ls):
ans.append([ls[left-1],-1])
elif left==0:
ans.append([-1,ls[left]])
else:
ans.append([ls[left-1],ls[left]])
return ans