Longest subarray whose sum <= k
Longest subarray whose sum
Given an array
of
numbers and a key
, find the longest subarray of
for which the subarray sum is less than or equal to
.
In the following we describe an algorithm with time complexity
.
Algorithm LONGESTSUBARRAY(
,
)
Longest_subarray_k_improved.cpp LongestSubarrayK.java
Longest subarray whose sum
Given an array
In the following we describe an algorithm with time complexity
Algorithm LONGESTSUBARRAY(
Input: An array
and a real number 
Output: A pair of indices
, maximizing
, subject to ![\sum_{t = i}^j A[t] \leq k \sum_{t = i}^j A[t] \leq k](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sDPBHto2QdMNfYOGkRsgAYXvhLosD04ZpqByKd25mxJpnZ6UTYP6HqI8RjvKx0vY3M-kyr-pEPYhRLix1qcSTZbSSibvhF6INwQnVE9-TcZaKMk8CTqvMwgRrvKSFtCQZIZ8NbE29ww3NtxLlomm9-czWYAmSGLakEZNLNgZDNceKaGg=s0-d)
1. Compute the array
of partial sums, where
is the prefix sum of the first
numbers in
.
.
2.
3.
4.
5. for
down to 0
if![S[i] < {\rm smallest} S[i] < {\rm smallest}](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sZeW3AUaVuBTfPH6KgAI5igI5AYgxoFiReiDhoeWfrX71WtnXaX5nG0K6cxJWoWocNVnlxEyYz97VKKsYXmwdYkkGOMdpZUMNgwxmPRv2k0voTMSu2Uyfsc-qpr1OHTU0HK9E44gHxNrno9MbLBv7od1GjSOWvQhEPeA=s0-d)
![M \leftarrow M \cup \{(S[i], i)\} M \leftarrow M \cup \{(S[i], i)\}](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sVAzJIhHNm64xVxy0Kj8-MCO_hDmIyw0CthfVx5RCoQ6Q66aZERRPLWGQ9vUw_2xKcQ3IP8OKCpYMpykaduVUMaCQY0t__jOYiSi2HUSQxiOKJs6fpq9UrDB9hI6p02VD8-4RZAJiNBj6DUmbFbcUuRVE8Nuu9S3IZHjUnMMpgcFWaJVmR0I9ABC4=s0-d)
![{\rm smallest} \leftarrow S[i] {\rm smallest} \leftarrow S[i]](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_t1_WDVT_Tqi0dhM5Ek8iGZ8Oh00MfAaQ6hv8ZhNNyMDhL0uy0p8BQq82_Rf2gkEH0GpcO_acvRqEzT4GwUu5coaW5rV8eqtYmMMLp8iqc8or41OQYoUYmLbcWzevfcMps666pvySzvlJEOgruxuXUVQCwQieYOg1R7cPUewDubIOFn=s0-d)
6.
7. for
up to 
if![S[i] > {\rm current} S[i] > {\rm current}](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vWUy-45XPzf1UTrN5_3Pfcc3xC6lmCHJRgTnUxMTkpkoVdQU5zHaNVl4rAnRSspCFn6LLuohw9unx1UlfoBOiLLxFILlB5aJTs9V2eVfFYfeWnSxZwnWDY_XFLudR_8oxWZx7OW10COKr07_CRpUHAuZ2il_6G3T1E=s0-d)
Use binary search to look for the rightmost element
in
such that
. If such an element exists, update
to
if 
![{\rm current} \leftarrow S[i] {\rm current} \leftarrow S[i]](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uPIrhKRt7KVENaFIR_LWZHlGy1jGQjOKNEvEPn6s8-J6B8PPnDolRSiXQAXgebqK4wRI-DErvq0vwp9LhuDYmRxL-F2vaWdXIyps5MXwqNzWjHUg-Sx_uqsHc1e3UM74jnZnMDNbW9P1Q36fpL5EB6ErnDWzRjhqjWZX5X80spMNlN=s0-d)
8. return
Find the longest subarray whose sum <= kOutput: A pair of indices
1. Compute the array
2.
3.
4.
5. for
if
6.
7. for
if
Use binary search to look for the rightmost element
8. return
Longest_subarray_k_improved.cpp LongestSubarrayK.java
public static Pair<Integer, Integer> findLongestSubarrayLessEqualK(
List<Integer> A, int k) {
// Build the prefix sum according to A.
List<Integer> prefixSum = new ArrayList<>();
int sum = 0;
for (int a : A) {
sum += a;
prefixSum.add(sum);
}
List<Integer> minPrefixSum = new ArrayList<>(prefixSum);
for (int i = minPrefixSum.size() - 2; i >= 0; --i) {
minPrefixSum.set(i,
Math.min(minPrefixSum.get(i), minPrefixSum.get(i + 1)));
}
Pair<Integer, Integer> arrIdx = new Pair<>(0,
upperBound2(minPrefixSum, k) - 1);
for (int i = 0; i < prefixSum.size(); ++i) {
int idx = upperBound2(minPrefixSum, k + prefixSum.get(i)) - 1;
if (idx - i - 1 > arrIdx.getSecond() - arrIdx.getFirst()) {
arrIdx = new Pair<>(i + 1, idx);
}
}
return arrIdx;
}
Correctness of the Algorithm
The key is to observe the following two facts.
Claim: (1) If two indices
satisfies that
, then
cannot appear in an optimum solution; (2) If two indices
satisfies that
, then
cannot appear in an optimum solution.
Proof: For any index
,
, note that the subarray sum of
is less than the subarray sum of
, and the length of the subarray $A[i..r']$ is greater than the length of the subarray
(although both length might be negative, but the statement still holds). Therefore,
is preferable over
. This is also the reason why we compute the strictly increasing sequence of
.
The second statement follows a similar reasoning.
Claim: (1) If two indices
Proof: For any index
The second statement follows a similar reasoning.
Time Complexity and Space Complexity
Step 1, computing the prefix sums, takes
time. Step 4, computing the array
, takes
time. Step 7 takes
time as each iteration takes
time.
Please read full article from Longest subarray whose sum <= kStep 1, computing the prefix sums, takes