题目
给定一棵二叉搜索树,请找出其中第 k 大的节点的值。
知识点
- 二叉搜索树:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。(摘自百度百科)
- 二叉树的前序、中序、后序遍历
解题
思路
既然二叉树的节点在大小顺序上有一定规律,那么只要按照一定顺序对其进行读取,便可构建一个从小到大(或从大到小)的数组。然后读取指定位置的数据进行返回就可以得到答案。
示例代码:
// 一个从大到小的可变数组
List<Integer> list = new ArrayList<>();
// 主函数
public int kthLargest(TreeNode root, int k) {
midSort(root);
// 判断异常情况
if (k>list.size()){
return -1;
}
return list.get(k);
}
// 按照右子树 → 根节点 → 左子树的顺序进行遍历,从而得到从大到小的数组
private void midSort(TreeNode root) {
if (Objects.isNull(root)){
return;
}
midSort(root.right);
list.add(root.val);
midSort(root.left);
}
思路改进
题目要求得到第k大的数。而思路是先得到排序好的所有数据,然后找到第k大。那么,既然list里面的元素是被从大到小填入的,可不可以填到第k大,就不填入了,直接返回呢?相当于提前终止,从而缩短时间。
要找第k大的数字,只需要把前(k-1)个排掉,然后剩下的里面最大的即可。
示例代码
// 记录结果
int result = 0;
// 记录顺序
int index = 0;
public int kthLargest(TreeNode root, int k) {
index = k;
midSort(root);
return result;
}
private void midSort(TreeNode root) {
if (Objects.isNull(root)){
return;
}
midSort(root.right);
// 每次读取,相当于取出当前最大的那个数字了。则index-1。
// 当--index后为0,说明已经从大到小读取了index个数字,
// 此时读取的数就是想要的结果
if (--index==0){
result = root.val;
return;
}
midSort(root.left);
}
耐思