如何在O(n)时间复杂度中找到总和k的所有子阵列?

时间:2017-09-05 19:19:33

标签: java arrays

我可以使用以下代码搜索带总和k的子数组:

public static void subarraySum(int[] arr, int sum) {

    int start=0;
    int currSum=arr[0];

    for(int i = 1;i<=arr.length;i++) {
        while(currSum>sum ) {
            currSum-=arr[start];
            start++;
        }
        if(currSum==sum) {
            System.out.println(start + " " + (i-1) + " index");
            start=i;
            currSum=0;
        }
        if(i<arr.length) {
            currSum +=arr[i];
        }

    }

这适用于像{15,2,4,8,9,5,10,23}这样的数组。此输出将是2个子阵列{2,4,9,8}和{23}。

然而,对于像{1,5,2,5,1,3}这样的数组,这只会给我输出为1个子数组但是有2个子数组,其中和7是{5,2}和{2, 5}。 有关如何调整上述代码以在第二个数组中给出正确答案的任何建议吗?

2 个答案:

答案 0 :(得分:3)

算法并不复杂,我会解释这个想法并让实现给你试试。

你需要有两个索引i,j,让它们都从第一个元素开始,现在在它们之间取两个子数组(最初因为它们都在同一个地方没有子数组)并进行以下测试。

  • 如果它的总和等于你的目标,那么添加当前的子数组

  • 如果总和小于你的目标,则向右移动j以包含一个 更多元素并再次进行测试

  • 如果总和大于您的目标,则向右移动i 来自子阵列的第一个元素再次进行测试。

最后,你将得到所有的子数组,其总和等于玩具目标

  

请注意此解决方案仅适用于正数

答案 1 :(得分:0)

是的,我太慢了。虽然我正在解决这个问题以提供代码,但我们有一个正确的algorytm答案。来自我的+1,以及我的代码的解决方案(我很多时候在采访中有这个问题)

public static List<int[]> subarraySum(int[] arr, int sum) {
    List<int[]> res = new ArrayList<>();
    int[] tmp;
    int start = 0;  // inclusive
    int end = 0;    // exclusive
    int currSum = 0;

    do {
        if (end == arr.length && currSum < sum)
            break;
        if (currSum > sum)
            currSum -= arr[start++];
        else if (currSum < sum)
            currSum += arr[end++];
        else if (currSum == sum) {
            res.add(tmp = new int[end - start]);
            System.arraycopy(arr, start, tmp, 0, tmp.length);
            currSum -= arr[start];
            start++;
        }
    } while (start <= arr.length && end <= arr.length);

    return res;
}

看起来是正确的,但我只在几种情况下测试了这个解决方案。