在二分搜索树中找到第k个最小的节点

时间:2018-10-27 20:59:16

标签: algorithm data-structures binary-search-tree tree-traversal

class Solution {
    public int kthSmallest(TreeNode root, int k) {
        int cnt = 0;
        int val = -1000;
        int res  = inorderTraversal(root,k,cnt,val);
        return res;
    }


    public int inorderTraversal(TreeNode root,int k,int cnt,int val){

         if (root == null) 
            return val; 

        inorderTraversal(root.left,k,cnt,val);
        cnt++;
        //System.out.println(root.val);
        if(cnt == k){
            //System.out.println(root.val);
            val = root.val;
            return val;
        }
        inorderTraversal(root.right,k,cnt,val);
        return val;
    }
}

所以我知道,我可以使用inorder traversal来找到第k个最小的节点。我一经发现就无法理解如何将其发送回递归的最底层。我在这里找不到答案。

注意:这不是家庭作业或任何作业。我对递归感到困惑,并试图理解这种方法

问题来自https://leetcode.com/problems/kth-smallest-element-in-a-bst/

1 个答案:

答案 0 :(得分:1)

实际上,您可以使用调试器在执行递归时可视化堆栈帧。

让我们在一个简单的BST上对其进行分析:

      2

  1       3

从root = 2开始(TopStackFrame:{root = 2,k = 3,cnt = 0,val = -1000})

|

root!= null

|

因此变为1(TopStackFrame:{root = 1,k = 3,cnt = 0,val = -1000})

|

现在移到1的左侧(TopStackFrame:{root = null,k = 3,cnt = 0,val = -1000})

|

root为null,它将返回val(已删除堆栈顶部)

|

现在回到1

|

cnt ++ cnt变为1(TopStackFrame:{root = 1,k = 3,cnt = 1,val = -1000})

|

cnt!= k 转到1的右边(TopStackFrame:{root = null,k = 3 cnt = 1,val = -1000})

|

1的权利为空 返回val(已删除堆栈顶部)

|

然后再次返回val(TopStackFrame:{root = 1,k = 3,cnt = 1,val = -1000})

|

现在1完成。

|

现在您来到2(TopStackFrame:{root = 2,k = 3,cnt = 0,val = -1000})

现在 您是否看到cnt的值不是1而是0,因为每个stackframe都有自己的变量集。

类似的事情发生在变量val上。

有几种解决方法:

a)您可以在类中将它们声明为成员变量,并在递归中更新它们,因此您无需在递归中返回任何内容,只需声明一个不返回任何内容但更新这些成员变量的方法即可。

b)您可以使用像int [] val,int [] cnt这样的数组,每个数组包含一个元素,并在每次递归调用中更新它们的元素。

c)您可以使用迭代顺序遍历并在计数达到k时获取值。

我更喜欢'c'。它更加干净,不必声明成员变量或数组。它还可以防止高度不平衡的树中的stackoverflow异常。