题目: 一棵二叉搜索树,请找出其中第k大的节点
思路
自己的思路是层序遍历,再排序,找到第k大的节点,然而却忽略了最重要的一个线索二叉搜索树!
二叉搜索树: 即二叉排序树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值(左<根<右)。
所以本题中,找第k大的数即按照降序排序后,第k个数即为所求。而根据BST的性质,降序排序就是“右根左”的中序遍历得到的顺序。
代码
public int kthLargest(TreeNode root, int k) {
List<Integer> list = new ArrayList<>();
dfs(root,list);
return list.get(k-1);
}
private void dfs(TreeNode root, List list) {
if(root==null) return;
dfs(root.right,list);
list.add(root.val);
dfs(root.left,list);
}
优化
private int count=0, num;
public int kthLargest(TreeNode root, int k) {
dfs(root,k);
return num;
}
private void dfs(TreeNode root, int k) {
if(root==null) return;
dfs(root.right,k);
count++;
if(count==k) num=root.val;
dfs(root.left,k);
}
- 时间复杂度:O(N),当树退化为链表时(全部为右子节点),无论 kk 的值大小,递归深度都为 NN ,占用 O(N)O(N) 时间。
最差的情况是k==树的节点数,即要遍历所有节点 - 空间复杂度:O(N),最差的情况是当BST只有右子树时,退化成链表,需要O(N)的栈