给定一个具有唯一整数和数字K的BST。在BST中找到一对(a,b) a + b = k。
约束:
您无法更改树的结构,否则我们可以将其转换为已排序的双链表,并在O(N)中填充该对。
该方法应该就地。
需要O(N)溶液。
我想到了一些与运行两个指针相关的东西,一个是从左到右,另一个是从右到左,就像我们在排序数组中找到对一样。但是,我无法清楚地了解如何实施它?
答案 0 :(得分:8)
正如塞缪尔已经说过,我也认为你的解决方案应该有效。 两个指针或迭代器,一个从左到右(从小到大),一个从右到左(从大到小)。 如果(a + b)>然后k从右到左迭代一个(下一个较小的值),否则迭代另一个(下一个更大的值)。 如果> = b,您可以停止 即使在不平衡树的情况下,运行时也是线性的。 每个节点最多访问一次。
我认为在这种情况下,真正的函数递归会变得有些复杂。 因此,最好使用两个自制堆栈在一个函数中进行递归。 这样的事情:
a = b = root;
while (a.left) {
astack.push(a)
a = a.left
}
while (b.right) {
bstack.push(b)
b = b.right
}
while (a.value < b.value) {
if (a.value + b.value == k) found!
if (a.value + b.value < k) {
if (a.right){
a = a.right
while (a.left) {
astack.push(a)
a = a.left
}
} else a = astack.pop()
} else {
if (b.left){
b = b.left
while (b.right) {
bstack.push(b)
b = b.right
}
} else b = bstack.pop()
}
}
答案 1 :(得分:2)
我同意2指针方法可行。我确实想到了同样的事情。但是,如果我们尝试使用递归,我认为代码会变得非常复杂/混乱。另一种方法是使用堆栈作为评价最高的答案。但是,如果我们必须使用空间来减少它的复杂性,我们可以完全避免使用2指针方法。
我在这里使用了不同的方法。以您想要的任何顺序遍历树,并将元素插入HashSet中。填充此集后,迭代set的元素,然后检查target_sum和当前数之间是否存在差异。如果它确实返回或移动到下一个元素。
这仍然是O(n)方法的顺序,但在我看来使用O(n)并且更容易理解。
答案 2 :(得分:1)
我们同时在正常顺序和反向顺序中遍历BST。反过来,我们从最右边的节点开始,这是最大值节点。在正常的顺序中,我们从最左边的节点开始,这是最小值节点。我们在两次遍历中添加当前节点的总和,并将此总和与给定的目标总和进行比较。如果总和与目标总和相同,则返回true。如果总和大于目标总和,我们以反向顺序遍历到下一个节点,否则我们在正常的顺序遍历中移动到下一个节点。如果任何遍历完成而没有找到一对,我们返回false。
boolean isPairPresent(Node3 root, int sum)
{
Stack<Node3> stack1 = new Stack<Node3>();
Stack<Node3> stack2 = new Stack<Node3>();
boolean done1 = false;
boolean done2 = false;
int val1 = 0, val2 = 0;
Node3 curr1 = root, curr2 = root;
while(true) {
while(done1 == false) {
if(curr1 != null) {
stack1.push(curr1);
curr1 = curr1.left;
} else {
if(stack1.isEmpty())
done1 = true;
else {
curr1 = stack1.pop();
val1 = curr1.data;
curr1 = curr1.right;
done1 = true;
}
}
}
while(done2 == false) {
if(curr2 != null) {
stack2.push(curr2);
curr2 = curr2.right;
} else {
if(stack2.isEmpty())
done2 = true;
else {
curr2 = stack2.pop();
val2 = curr2.data;
curr2 = curr2.left;
done2 = true;
}
}
}
if((val1 != val2) && (val1+val2 == sum)) {
System.out.println("Pair found: "+val1+" + "+val2+" = "+sum);
return true;
} else if(val1 + val2 > sum) {
done2 = false;
} else if(val1 + val2 < sum)
done1 = false;
if(val1 >= val2)
return false;
}
}
答案 3 :(得分:0)
上述问题的另一个解决方案(它需要O(n)空间,但实现比在BST中找到下一个更大/更小的元素要简单得多) 在给定的二叉树上执行inorder遍历并将元素存储在数组中。生成的数组将是一个排序的数组。首先将A [1] + A [n]与k
进行比较Initialize i=1, j=n
while(A[i]+A[j] <> k)
if A[i]+A[j] < k
i++;
else
j--;// typo
答案 4 :(得分:0)
首先对树进行Inorder遍历并将结果存储在Array a[]
中,然后再存储
i = 0 ; j = n;
while(i<=j<=n)
{
if(a[i]+a[j] == k)
{
printf("pair is == %d & %d \n", a[i],a[j]);
i++;
}
else if(a[i]+a[j] > k)
j--;
else if(a[i]+a[j] < k)
i++;
}