【发布时间】:2018-03-26 14:47:13
【问题描述】:
我正在尝试打印 BST 中的第 k 个最小元素。 第一个解决方案是使用中序遍历。 下一个解决方案是通过计算其左子树的大小来找到当前节点的索引。 完整的算法:
Find size of left subtree:
1.If size = k-1, return current node
2.If size>k return (size-k)th node in right subtree
3.If size<k return kth node in left subtree
这可以使用一个单独的计数函数来实现,看起来像
public class Solution {
public int kthSmallest(TreeNode root, int k) {
//what happens if root == null
//what happens if k > total size of tree
return kthSmallestNode(root,k).val;
}
public static TreeNode kthSmallestNode(TreeNode root,int k){
if(root==null) return root;
int numberOfNodes = countNodes(root.left);
if(k == numberOfNodes ) return root;
if(k<numberOfNodes ) return kthSmallestNode(root.left,k);
else return kthSmallestNode(root.right,k-numberOfNodes );
}
private static int countNodes(TreeNode node){
if(node == null) return 0;
else return 1+countNodes(node.left)+countNodes(node.right);
}
}
但我看到我们多次计算同一棵树的大小,因此一种方法是维护一个数组来存储这些大小,就像 DP 方式一样。
但我想为此编写一个递归解决方案。这是我编写的代码。
class Node {
int data;
Node left;
Node right;
public Node(int data, Node left, Node right) {
this.left = left;
this.data = data;
this.right = right;
}
}
public class KthInBST
{
public static Node createBST(int headData)
{
Node head = new Node(headData, null, null);
//System.out.println(head.data);
return head;
}
public static void insertIntoBst(Node head, int data)
{
Node newNode = new Node(data, null, null);
while(true) {
if (data > head.data) {
if (head.right == null) {
head.right = newNode;
break;
} else {
head = head.right;
}
} else {
if (head.left == null) {
head.left = newNode;
break;
} else {
head = head.left;
}
}
}
}
public static void main(String[] args)
{
Node head = createBST(5);
insertIntoBst(head, 7);
insertIntoBst(head, 6);
insertIntoBst(head, 2);
insertIntoBst(head, 1);
insertIntoBst(head, 21);
insertIntoBst(head, 11);
insertIntoBst(head, 14);
insertIntoBst(head, 3);
printKthElement(head, 3);
}
public static int printKthElement(Node head, int k)
{
if (head == null) {
return 0;
}
int leftIndex = printKthElement(head.left, k);
int index = leftIndex + 1;
if (index == k) {
System.out.println(head.data);
} else if (k > index) {
k = k - index;
printKthElement(head.right, k);
} else {
printKthElement(head.left, k);
}
return index;
}
}
这是打印正确答案但多次,我想通了为什么它打印多次但不明白如何避免它。 而且如果我想返回节点而不是仅仅打印我该怎么做? 谁能帮我解决这个问题?
【问题讨论】:
-
"通过计算左子树的大小找到当前节点的索引"。这并不比中序遍历好,除非每个节点始终保持其子树的大小。
-
是的,你是对的。但这只是另一种方法,我想用递归来实现它
-
您可以通过删除
else部分 [else { printKthElement(head.left, k); }] 来避免多次打印该值。就返回节点而言,我想不出任何东西,因为我在java中不是那么好,java也是按值传递的。我想到了两件事:1.取一个类变量(我个人不喜欢这种方式)2.使用回调(Overkill) -
OP 还感兴趣吗?我想到了一个可行的解决方案。
-
@vishal-wadhwa 是的,我仍在寻找解决方案。
标签: algorithm recursion data-structures binary-search-tree