两个总和:如何实现O(1)空间复杂度的解决方案?

时间:2014-01-04 04:58:10

标签: java

LeetCode中描述了经典的Two Sum问题。

我知道如何使用哈希表来解决它,这导致O(n)额外空间。现在我想用O(1)空间来解决它,所以我首先对数组进行排序,然后使用两个指针来找到两个整数,如下面的(不正确的)代码所示。

public int[] twoSum(int[] numbers, int target) {
        java.util.Arrays.sort(numbers);
        int start = 0, end = numbers.length - 1;
        while(start < end) {
            if(numbers[start] + numbers[end] < target) {
                start++;
            }
            else if(numbers[start] + numbers[end] > target) {
                end--;
            }
            else {
                int[] result = {start + 1, end + 1};
                return result;
            }
        }
        return null;
}

此代码不正确:我在排序后返回索引。那么我将如何跟踪所选整数的原始索引?还是有其他O(1)空间解决方案?谢谢。

2 个答案:

答案 0 :(得分:3)

有一些限制可以实现什么,什么不可以实现。有一些参数相互依赖。时间与时间在算法方面,空间复杂性是两个这样的参数。

如果您想优化空间问题,除了在某些特殊情况下,它会增加大多数情况下的时间复杂度。

在这个问题中,如果您不想增加空间复杂度并希望保留原始索引,唯一的方法是不对数组进行排序并从数组中取出每两个数字组合并检查是否他们的总和是你的目标。这意味着代码变得类似于下面的代码。

while(i < n)
{
   while(j < n)
   {
      if(i!=j && arr[i]+arr[j]==target)
      {
            int[] result = {i, j};
                return result;
      }
      j++;
   }
   i++;
}

正如您所看到的,这显然是一种O(n ^ 2)算法。即使在你编写的程序中,排序也会像O(nlogn)。

所以,最重要的是,如果你想减少空间复杂性,它会增加时间复杂度。

答案 1 :(得分:2)

如果您只担心空间复杂性而不是时​​间复杂性,那么您不需要排序。这样,跟踪原始指数的整个问题就消失了。

int[] twoSum(int[] numbers, int target) {
    for (int i = 0; i < numbers.length-1; i++) {
        for (int j = i+1; j < numbers.length; j++) {
            if (numbers[i] + numbers[j] == target)
                return new int[]{i+1, j+1};
        }
    }
    return null;
}

如果你想返回所有这样的对,而不仅仅是第一个,那么只需继续迭代而不是立即返回(当然,返回类型必须更改为列表或二维数组或.. 。)。