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_vYbqfMYrugUnKIBJ1nSi_jY549LclaQBDN4MNwEFMARAs8ehtEORAUANieCnM9alapu3McNnomNHhMzZBJ-CYCPG-KdXkrr557v23WZMWJrjX470W2XvcRTqUtwA_E6WoITs2vKSQjTklqU7-8HrRFIYSaM3PI2Up1_QI598H5aYz4Uw=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_tPv0USgiMxHPzKXL870c9RTL1bzH0dgUcOF9FO-J0rvUtZwyeVcFvqQzCAuyPysXX-y7zPpd-rrxE5CeNA_5tg0rLyVA0ONwpRoFJAqgvdwRHraloHD8rL_ybUqv3AH07LryhMMYYrf54D5NgRmqhKtAxjt4V3O2hjPw=s0-d)
        ![M \leftarrow M \cup \{(S[i], i)\} M \leftarrow M \cup \{(S[i], i)\}](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tNGiROlgF_2nX01X5ngkKaj6C3_TTHYoin4C6k1lwQESOsxOnxjm-udUUvr9gwE_EUaY3abmYUb9Mzg8QSMMhNuXhwDCFDXYUh8m8i6mQ-izqdbg_7FO6rEGjDGl0-p8dAaE09Kw0fRawey8mIds-7c5zk9Ojsp5PzvSairyNvh1-kclQHKFwBt7M=s0-d)
        ![{\rm smallest} \leftarrow S[i] {\rm smallest} \leftarrow S[i]](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sdQysN-8v7jHbNr2LoDQQ6QUHv8HJ6Ku3K2ajXNiCf8Pe8IaxcpBlLfiQH9z-peldp0Tuh0-zSWvMv5cpMkZCPP6RTa19WcBBTmFAUMh_2nLI7lWfyWuZUMvlMumTFY5349NHVL8EBMbvGPcjQ-YBllrv-ObE3Vm3Aix7Ck91XvnGi=s0-d)
6.
7. for
 up to 
if![S[i] > {\rm current} S[i] > {\rm current}](https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sZwpcHOF3uG9LrMcEkKcNM4BXTI9d4pvt8uEybJgO-hhTIOb0JkKv9Ou22qD0-M7Vj76Rq0esUnddw2tLWrq5IEMyuKsEPf9_ki25vOt-3IL_oEx6bYfyRkojF9QvSSSR_CLKGkx6-YWyjgzaSM9DzRkn-dY1gzgaL=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_tT4HCntv3nWXkv8pCULyNWoFJNpwGSA1Jj9jHwa0B4Ku6BUL50kySscPJAL9ufgfQPVGit-0JbzZcPq3bzG5HMIeCbIQQLupX3soBCwfLJ3uA_Ufnj9aQigVRl_cR7k5NrPKgau_pc8VOkhmN91ndZ3KohXkyB_caCbAMcCIvqK7du=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