-
Notifications
You must be signed in to change notification settings - Fork 176
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
83 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# 二叉搜索树的第 k 大的节点 | ||
|
||
## 题目描述 | ||
|
||
给定一棵二叉搜索树,请找出其中第 k 大的节点。 | ||
|
||
示例 1: | ||
|
||
``` | ||
输入: root = [3,1,4,null,2], k = 1 | ||
3 | ||
/ \ | ||
1 4 | ||
\ | ||
2 | ||
输出: 4 | ||
``` | ||
|
||
示例 2: | ||
|
||
``` | ||
输入: root = [5,3,6,2,4,null,null,1], k = 3 | ||
5 | ||
/ \ | ||
3 6 | ||
/ \ | ||
2 4 | ||
/ | ||
1 | ||
输出: 4 | ||
``` | ||
|
||
## 解题基本知识 | ||
|
||
二叉搜索树(Binary Search Tree)又名二叉查找树、二叉排序树。它是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。 | ||
|
||
## 解法 | ||
|
||
[在线链接](https://codesandbox.io/s/erchasousuoshudedi-k-dadejiedian-vfpbh?file=/index.html) | ||
|
||
利用二叉搜索树的特性进行中序遍历。先遍历左节点,然后根节点,最后遍历右节点,得到的是一个递增序列,那么序列的倒序为递减序列。因此这道题我们可以转变为求二叉搜索树中序遍历倒序的第 k 个数。 | ||
|
||
![解法图示](https://user-images.githubusercontent.com/15681693/130164388-85e96093-9336-4174-b139-59e83d972a20.png) | ||
|
||
```javascript | ||
/** | ||
* Definition for a binary tree node. | ||
* function TreeNode(val) { | ||
* this.val = val; | ||
* this.left = this.right = null; | ||
* } | ||
*/ | ||
/** | ||
* @param {TreeNode} root | ||
* @param {number} k | ||
* @return {number} | ||
*/ | ||
const kthLargest = (root, k) => { | ||
let res = null; // 初始化返回值 | ||
// 因为需要倒序第 k 个,所以处理是右节点,根节点,然后左节点 | ||
const dfs = (root) => { | ||
if (!root) return; // 如果当前节点为 null,本轮处理结束 | ||
dfs(root.right); // 开始处理右节点 | ||
if (k === 0) return; // k 值 为 0,代表已经处理的节点超过目标节点,本轮处理结束 | ||
if (--k === 0) { | ||
// 当 k 值 减 1 为 0,表示已经到了我们想要的 k 大 节点,保存当前值 | ||
res = root.val; | ||
} | ||
dfs(root.left); // 处理左节点 | ||
}; | ||
dfs(root); // 从初始化节点开始处理 | ||
return res; | ||
}; | ||
``` | ||
|
||
### 复杂度分析: | ||
|
||
- 时间复杂度 O(N):无论 k 的值大小,递归深度都为 N,占用 O(N) 时间。 | ||
- 空间复杂度 O(N):无论 k 的值大小,递归深度都为 N,占用 O(N) 空间。 | ||
|
||
### 参考资料 | ||
|
||
1. [剑指 offer](https://book.douban.com/subject/6966465/) |