我有一个整数数组(不一定排序),我想找到一个连续的子数组,其值的总和最小,但大于特定值K
e.g。 :
输入:数组:{1,2,4,9,5}
,键值:10
输出:{4,9}
我知道在O(n ^ 2)
中执行此操作很容易,但我希望在O(n)
我的想法:我无法在O(n)
中找到这个,但我能想到的只有O(n^2)
时间复杂度。
答案 0 :(得分:10)
我们假设它只能有正值。
然后很容易。
解决方案是最小(最短)连续子阵列之一,其总和为> K
。
取两个索引,一个用于子阵列的开头,一个用于结束(一个用于结束),从end = 0
和start = 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;
}