给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。
示例 1:
输入:root = [3,1,4,null,2], k = 1
输出:1示例 2:
输入:root = [5,3,6,2,4,null,null,1], k = 3
输出:3提示:
- 树中的节点数为
n。 1 <= k <= n <= 1040 <= Node.val <= 104
进阶:如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化算法?
解题思路:中序遍历 + 剪枝
其实这道题就是利用二叉搜索树的中序遍历之后得到有序序列的特性,所以我们只需要通过中序遍历来遍历一下二叉树,然后用一个全局变量或者成员变量 ret 来记录下第 k 个节点,至于如何判断是第 k 个节点,我们也可以搞一个全局变量 count,初始值就是题目传入的 k,然后每遍历一个节点进行中序处理的时候就让 count--,然后判断一下 count 是否为零,是的话说明此时已经是要找的节点了,则直接返回即可!
此外,我们也可以做个剪枝操作,因为拿到第 k 个节点之后,后面的遍历就无意义了,所以我们只需要在递归函数出口添加一个判断,判断如果 count 为零的话,说明前面已经找到了第 k 个节点了,则直接返回,减少递归调用开销!
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
int count; // 初始化为最小的第k个数,每次遍历一个节点就进行减减
int ret; // 最终的返回结果
public:
int kthSmallest(TreeNode* root, int k) {
count = k;
ret = 0;
dfs(root);
return ret;
}
void dfs(TreeNode* root)
{
// 递归函数出口(顺便判断count,进行剪枝操作)
if(root == nullptr || count == 0)
return;
// 中序遍历,先递归到最左孩子
dfs(root->left);
// 然后处理当前节点,如果--count减为0了直接返回
if(--count == 0)
{
ret = root->val;
return;
}
// 最后处理右孩子
dfs(root->right);
}
};