简体   繁体   English

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

[英]Find the kth smallest node in binary search tree

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;
    }
}

So I understood, I can use inorder traversal to find the kth smallest node. 因此我了解到,我可以使用inorder traversal来找到第k个最小节点。 I am unable to understand, as soon as I find it, how do I send it back to the bottom stack of recursion. 我一经发现就无法理解如何将其发送回递归的最底层。 I am failing to get an answer here. 我在这里没有得到答案。

Note: This is not homework or any assignment. 注意:这不是家庭作业或任何作业。 I am confused about recursion and trying to understand the approach 我对递归感到困惑,并试图理解这种方法

Questiun is from https://leetcode.com/problems/kth-smallest-element-in-a-bst/ Questiun来自https://leetcode.com/problems/kth-smallest-element-in-a-bst/

Actually you could use a debugger to visualize stack frames as your recursion is executed. 实际上,您可以使用调试器在执行递归时可视化堆栈帧。

Lets analyze it on a simple BST like: 让我们在一个简单的BST上进行分析:

      2

  1       3

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

| |

root != null 根!=空

| |

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

| |

now goes to left of 1 ( TopStackFrame: { root = null, k = 3, cnt = 0, val = -1000 } ) 现在转到1的左侧(TopStackFrame:{root = null,k = 3,cnt = 0,val = -1000})

| |

root is null it returns val ( top of stack removed ) root为null,它将返回val(已删除堆栈顶部)

| |

now come back to 1 现在回到1

| |

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

| |

cnt != k goes to right of 1 ( TopStackFrame: { root = null, k = 3 cnt = 1, val = -1000 } ) cnt!= k移到1的右边(TopStackFrame:{root = null,k = 3 cnt = 1,val = -1000})

| |

right of 1 is null returns val ( top of stack removed ) 1的右边为null返回val(删除堆栈顶部)

| |

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

| |

now 1 is done. 现在1完成。

| |

now you come to 2 ( TopStackFrame: { root = 2, k = 3, cnt = 0, val = -1000 } ) 现在您进入2(TopStackFrame:{root = 2,k = 3,cnt = 0,val = -1000})

Now do you see that value of cnt is not 1 but 0 because each stackframe has its own set of variables. 现在您会看到cnt的值不是1而是0,因为每个stackframe都有自己的变量集。

Similar thing happens with the variable val . 变量val发生类似的情况。

There are several options to resolve this : 有几种解决方案:

a) You could declare these as member variables in your class and update these in your recursion so you dont need to return anything with your recursion, just declare a method that doesn't return anything but updates these member variables. a)您可以在类中将它们声明为成员变量并在递归中更新它们,因此您无需在递归中返回任何内容,只需声明一个不返回任何内容但更新这些成员变量的方法即可。

b) You could use arrays like int[] val, int[] cnt with each one containing one element and update their elements in each recursive call. b)您可以使用int [] val,int [] cnt之类的数组,每个数组包含一个元素,并在每次递归调用中更新它们的元素。

c) You could use an iterative inorder traversal and get the value when count reaches k. c)您可以使用迭代有序遍历并在计数达到k时获取值。

I would prefer 'c'. 我更喜欢'c'。 It is much cleaner, doesn't have to declare member variables or arrays. 它更加干净,不必声明成员变量或数组。 It also prevents stackoverflow exceptions in highly unbalanced trees. 它还可以防止高度不平衡的树中的stackoverflow异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM