在BST

时间:2018-02-04 20:10:25

标签: c++ binary-search-tree

我正在尝试从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的价值。

2 个答案:

答案 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个最小值。否则,还需要搜索正确的子树。