带有和约束的子数组的O(n)解

时间:2019-10-10 22:37:09

标签: algorithm subset complexity-theory subset-sum

我正在尝试改善关于以下两个子阵列问题的直觉。

问题之一

Return the length of the shortest, non-empty, contiguous sub-array of A with sum at least 
K. If there is no non-empty sub-array with sum at least K, return -1

我在网上遇到了O(N) solution

public int shortestSubarray(int[] A, int K) {
    int N = A.length;
    long[] P = new long[N+1];
    for (int i = 0; i < N; ++i)
        P[i+1] = P[i] + (long) A[i];

    // Want smallest y-x with P[y] - P[x] >= K
    int ans = N+1; // N+1 is impossible
    Deque<Integer> monoq = new LinkedList(); //opt(y) candidates, as indices of P

    for (int y = 0; y < P.length; ++y) {
        // Want opt(y) = largest x with P[x] <= P[y] - K;
        while (!monoq.isEmpty() && P[y] <= P[monoq.getLast()])
            monoq.removeLast();
        while (!monoq.isEmpty() && P[y] >= P[monoq.getFirst()] + K)
            ans = Math.min(ans, y - monoq.removeFirst());

        monoq.addLast(y);
    }

    return ans < N+1 ? ans : -1;
}

似乎在保持滑动窗口有双端队列。看起来像是Kadane算法的一种变体。

问题二

Given an array of N integers (positive and negative), find the number of 
contiguous sub array whose sum is greater or equal to K (also, positive or 
negative)"

我所见到的最好的解决方案是O(nlogn),如以下answer所述。

tree = an empty search tree
result = 0
// This sum corresponds to an empty prefix.
prefixSum = 0
tree.add(prefixSum) 
// Iterate over the input array from left to right.
for elem <- array:
    prefixSum += elem
    // Add the number of subarrays that have this element as the last one
    // and their sum is not less than K.
    result += tree.getNumberOfLessOrEqual(prefixSum - K) 
    // Add the current prefix sum the tree.
    tree.add(prefixSum)
print result

我的问题

  1. 我的直觉是算法一是Kandane算法的一种变体吗?

  2. 如果是,是否可以使用此算法的变体(或其他O(n)解决方案)来解决问题二?

  3. 为什么只有两个问题看起来很相似,O(nlogn)才能解决问题?

0 个答案:

没有答案