Java 在二叉搜索树中有效地找到第k个最小元素?
今天我遇到了下面的面试问题,我提出了下面提到的递归和迭代的解决方案,但不知为什么面试官不高兴。我不知道为什么 给定一个二叉搜索树,找到其中的第k个最小元素 有没有更好的方法可以用递归或迭代的方式解决这个问题Java 在二叉搜索树中有效地找到第k个最小元素?,java,algorithm,data-structures,binary-search-tree,Java,Algorithm,Data Structures,Binary Search Tree,今天我遇到了下面的面试问题,我提出了下面提到的递归和迭代的解决方案,但不知为什么面试官不高兴。我不知道为什么 给定一个二叉搜索树,找到其中的第k个最小元素 有没有更好的方法可以用递归或迭代的方式解决这个问题 /***************************************************** * * Kth Smallest Recursive * ************************************************
/*****************************************************
*
* Kth Smallest Recursive
*
******************************************************/
public int kthSmallestRecursive(TreeNode root, int k) {
int count = countNodes(root.left);
if (k <= count) {
return kthSmallestRecursive(root.left, k);
} else if (k > count + 1) {
return kthSmallestRecursive(root.right, k - 1 - count);
}
return root.data;
}
public int countNodes(TreeNode n) {
if (n == null)
return 0;
return 1 + countNodes(n.left) + countNodes(n.right);
}
/*****************************************************
*
* Kth Smallest Iterative
*
******************************************************/
public int kthSmallestIterative(TreeNode root, int k) {
Stack<TreeNode> st = new Stack<>();
while (root != null) {
st.push(root);
root = root.left;
}
while (k != 0) {
TreeNode n = st.pop();
k--;
if (k == 0)
return n.data;
TreeNode right = n.right;
while (right != null) {
st.push(right);
right = right.left;
}
}
return -1;
}
/*****************************************************
*
*第k最小递归
*
******************************************************/
公共int-kthsmallestrestrive草书(树根,int-k){
int count=countNodes(root.left);
如果(k计数+1){
返回kthsmallestrestre草书(root.right,k-1-count);
}
返回root.data;
}
公共int countNodes(树节点n){
如果(n==null)
返回0;
返回1+countNodes(n.left)+countNodes(n.right);
}
/*****************************************************
*
*第k最小迭代法
*
******************************************************/
公共int KTHSMALLISTIERATIVE(树根,int k){
Stack st=新堆栈();
while(root!=null){
圣推(根);
root=root.left;
}
while(k!=0){
TreeNode n=圣波普();
k--;
如果(k==0)
返回n.data;
树节点右=n.右;
while(右!=null){
圣普什(右);
右=右。左;
}
}
返回-1;
}
我提到上述两种解决方案的复杂性都是O(节点深度),即O(logn)
我的迭代版本需要额外的空间。有没有什么方法可以在没有额外空间的情况下完成它?首先,我怀疑它是否需要O(logn)。对于一般的二叉搜索树,它至少是O(n) 对于香草bst,您可以进行迭代或递归,这两种方法都是模拟相同的ignorer遍历过程,具有最差的时间复杂度O(n)和空间复杂度O(logn)(注意,即使递归解决方案也可以从堆栈中获取O(logn)空间) 但是,如果可以稍微更改数据结构,则可以加快速度或使用更少的空间:
public int printInorder(节点,int k)
{
如果(node==null | | k,你肯定比logn做得更好。他们提到了什么具体的事情吗?你怎么知道他是否不高兴?仅仅一次调用countNodes需要多长时间?计算树中的所有节点(或树中的一半节点)需要多长时间?不是O(logn)。此外,您不必要地多次查看同一个节点-您对它们进行计数,然后递归,然后再次计数,然后递归,等等。您所需要的只是按序遍历中的第k个元素。您的迭代版本似乎正在这样做。递归版本效率不高。@Dukeling所以我的迭代版本仅在重新执行时才有效草书一个有问题,对吗?因为我多次检查相同的节点,你能帮我理解为什么它不是O(logn).第三个选项怎么样?我们不能改变数据结构,需要找到它的原样,那么以最佳方式递归和迭代的复杂性是什么?嗨,john。上面提到了两个选项:对于香草bst,这是我们能做的最好的。嗨,Nicholas,这是为了查找某个元素,而不是第k个最大或最小的元素。B但到目前为止,我的递归解是o(n^2)时间复杂度,对吗?o(1)空间复杂度?@john是的。抱歉这个错误。在最坏的情况下,你的解会取o(n2),而o(1)空间复杂度。我的观点是正确的。@john:我的递归解[有…]o(1)空间复杂度?
只有当你忽略o(n)时才可以调用堆栈以保留需要重新访问的节点(如果需要)。
public int printInorder(Node node, int k)
{
if (node == null || k <= 0) //Stop traversing once you found the k-th smallest element
return k;
/* first recur on left child */
k = printInorder(node.left, k);
k--;
if(k == 0) {
System.out.print(node.key);
}
/* now recur on right child */
return printInorder(node.right, k);
}