从BST找到两个数字,总和给定数字K.

时间:2012-09-05 21:17:13

标签: c performance algorithm data-structures time-complexity

给定一个具有唯一整数和数字K的BST。在BST中找到一对(a,b)     a + b = k。

约束:

您无法更改树的结构,否则我们可以将其转换为已排序的双链表,并在O(N)中填充该对。

该方法应该就地。

需要O(N)溶液。

我想到了一些与运行两个指针相关的东西,一个是从左到右,另一个是从右到左,就像我们在排序数组中找到对一样。但是,我无法清楚地了解如何实施它?

5 个答案:

答案 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++;
}