我今天面临以下面试问题,我提出了如下所述的递归和迭代解决方案,但面试官不知何故不满意。我不确定为什么。
给出二叉搜索树,在其中找到第k个最小元素。
是否有更好的方法以递归或迭代的方式解决此问题?
/*****************************************************
*
* 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;
}
我在上述两种解决方案中都将复杂度称为O(节点深度),即O(log n)。
我的迭代版本占用更多空间。有没有没有多余空间的方法?
答案 0 :(得分:1)
首先,我不确定是否要使用O(logn)。原始二进制搜索树至少为O(n)。
对于香草,您可以进行迭代或递归,两者都是模拟相同的忽略者遍历过程,但时间复杂度为O(n)和空间复杂度为O(logn)(请注意,即使递归解决方案也可以采用O(logn)堆栈空间)。
但是,如果可以稍微更改数据结构,则可以加快处理速度或使用较少的空间:
如果您使用的是二进制搜索树,并且每个节点都记录了其下的总节点数,则可以将其视为已排序的数组,并使用O(logn)到达第k个元素时间和O(1)空间。
如果使用的二进制搜索树的每个节点都包含父指针和状态指示符,则可以以与原始解决方案相同的方式遍历该树。在途中,您标记节点是否为a。未遍历。2.遍历其左节点。3.遍历两个节点。那么您可以在O(n)时间和O(1)空间中做到这一点。
答案 1 :(得分:0)
datetimeobject.AfterDate.ToString(@"s", CultureInfo.InvariantCulture)
在递归方法的 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);
}
方法中,您遍历每个节点上的Tree进行计数。 countNodes()
操作是O(n),您正在对log(n)个节点执行操作。因此,递归解决方案的复杂度顺序为countNodes()
,而我上面提到的方法可以在O(n)中解决。