最小子阵列大于键

时间:2013-06-17 21:22:17

标签: arrays algorithm computer-science

我有一个整数数组(不一定排序),我想找到一个连续的子数组,其值的总和最小,但大于特定值K

e.g。 :

输入:数组:{1,2,4,9,5},键值:10

输出:{4,9}

我知道在O(n ^ 2)中执行此操作很容易,但我希望在O(n)

中执行此操作

我的想法:我无法在O(n)中找到这个,但我能想到的只有O(n^2)时间复杂度。

2 个答案:

答案 0 :(得分:10)

  

我们假设它只能有正值。

然后很容易。

解决方案是最小(最短)连续子阵列之一,其总和为> K

取两个索引,一个用于子阵列的开头,一个用于结束(一个用于结束),从end = 0start = 0开始。初始化sum = 0;min = infinity

while(end < arrayLength) {
    while(end < arrayLength && sum <= K) {
        sum += array[end];
        ++end;
    }
    // Now you have a contiguous subarray with sum > K, or end is past the end of the array
    while(sum - array[start] > K) {
        sum -= array[start];
        ++start;
    }
    // Now, you have a _minimal_ contiguous subarray with sum > K (or end is past the end)
    if (sum > K && sum < min) {
        min = sum;
        // store start and end if desired
    }
    // remove first element of the subarray, so that the next round begins with
    // an array whose sum is <= K, for the end index to be increased
    sum -= array[start];
    ++start;
}

由于两个索引仅递增,因此算法为O(n)

答案 1 :(得分:0)

对O(1)空间在O(n)时间内工作的正负数(不完全确定负数)的Java实现。

public static int findSubSequenceWithMinimumSumGreaterThanGivenValue(int[] array, int n) {

    if (null == array) {
        return -1;
    }

    int minSum = 0;
    int currentSum = 0;
    boolean isSumFound = false;
    int startIndex = 0;
    for (int i = 0; i < array.length; i++) {
        if (!isSumFound) {
            currentSum += array[i];
            if (currentSum >= n) {
                while (currentSum - array[startIndex] >= n) {
                    currentSum -= array[startIndex];
                    startIndex++;
                }
                isSumFound = true;
                minSum = currentSum;
            }
        } else {
            currentSum += array[i];
            int tempSum = currentSum;
            if (tempSum >= n) {
                while (tempSum - array[startIndex] >= n) {
                    tempSum -= array[startIndex];
                    startIndex++;
                }
                if (tempSum < currentSum) {
                    if (minSum > tempSum) {
                        minSum = tempSum;
                    }
                    currentSum = tempSum;
                }
            } else {
                continue;
            }
        }
    }
    System.out.println("startIndex:" + startIndex);
    return minSum;
}