我正在尝试从LeetCode解决以下问题:
https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/
目标是,给定BST,我们必须找出其中的第K个最小元素并返回其值。
我自己可以提出O(n)
时间和空间解决方案。但是我用在线帮助写的另一个解决方案要好得多:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int kthSmallestUtil(TreeNode* root, int& k) {
if(!root) return -1;
int value=kthSmallestUtil(root->left, k);
if(!k) return value;
k--;
if(k==0) return root->val;
return kthSmallestUtil(root->right, k);
}
int kthSmallest(TreeNode* root, int k) {
return kthSmallestUtil(root, k);
}
};
我已经理解了上述解决方案。我还通过在29,30,33和37处插入断点来调试它(https://onlinegdb.com/BJnoIkrLM)。但是,由于以下原因,我仍感到有点不安:
如果是来电kthSmallestUtil(root->left, k);
,我们会传递原始值k
;然后我们(可以理解)减少当前根的k
值(因为我们正在进行顺序遍历)。但是,当我们再次递归kthSmallestUtil(root->right, k);
时,为什么我们不通过k
的原始值?为什么正确的孩子会得到“优惠”待遇 - k
的递减值?
我知道因为调试k
的值如何变化而我们得到了最终的答案..但我正在寻找一些直觉,背后使用k
的原始值为左子女和减少对于正确的孩子,k
的价值。
答案 0 :(得分:0)
这个解决方案似乎假设一个有序的二叉搜索树。 这意味着树的左分支仅包含比当前节点val更小的值。因此,它首先递归到左分支,沿途递减k,然后如果k不是0,则递减当前元素的k。如果k仍不为0,则考虑右分支中的值,均大于当前节点值。
你需要理解的是k在k--中递减; line不是k的原始值,而是遍历整个左分支后的k值。
递归调用都会修改相同的k,因为k是通过引用传递的,而不是通过值传递
答案 1 :(得分:0)
代码的工作方式更少 - 在BST的左侧分支尽可能深入。当你到达最左边的叶子 - 最小的值 - 递减k
值并开始在BST的剩余部分中进行搜索。因为我们已经访问了整个树中的最小值并且我们正在搜索第k个最小值,所以我们必须在树的其余部分中搜索k-1
最小值(因为我们不再考虑这个最左边的叶子)。因此,如果k
等于零,则表示当前节点具有第k个最小值。否则,还需要搜索正确的子树。