Open In App

Largest subarray having sum greater than k

Given an array of integers and a value k, find the length of largest subarray having a sum greater than k.

Examples: 

Input : arr[] = {-2, 1, 6, -3}, k = 5
Output : 2
Largest subarray with sum greater than
5 is  {1, 6}.

Input : arr[] = {2, -3, 3, 2, 0, -1}, k = 3
Output : 5
Largest subarray with sum greater than
3 is {2, -3, 3, 2, 0}.

A simple solution is to one by one consider each subarray and find its sum. If the sum is greater than k, then compare the length of this subarray with maximum length found so far. Time complexity of this solution is O(n2).

An efficient solution is to use prefix sum and binary search. The idea is to traverse the array and store prefix sum and corresponding array index in a vector of pairs. After finding prefix sum, sort the vector in increasing order of prefix sum, and for the same value of prefix sum, sort according to index. Create another array minInd[], in which minInd[i] stores the minimum index value in range [0..i] in sorted prefix sum vector. After this, start traversing array arr[] and store sum of subarray arr[0..i] in sum. If the sum is greater than k, then-largest subarray having a sum greater than k is arr[0..i] having length i + 1. If the sum is less than or equal to k, then a value greater than or equal to k + 1 – sum has to be added to sum to make it at least k+1. Let this value be x. 

To add x to sum, -x can be subtracted from it because sum-(-x) = sum + x. So a prefix array arr[0..j] (j<i), is needed to be found having sum at most -x (at most -x because k+1-sum is the least value, now its negative is taken so it will be maximum value allowed). The resultant subarray arr[j+1..i] should be as large as possible. For this, the value of j should be as minimum as possible. Thus the problem reduces to finding a prefix sum having value at most -x and its ending index should be minimum. 

To find the prefix sum, binary search can be performed on the prefix sum vector. Let the index ind denotes that in prefix sum vector all prefix sum values up to index ind are less than or equal to -x. The minimum index value in range[0..ind] is minInd[ind]. If minInd[ind] is greater than i, then no subarray exists having sum -x in range[0..i-1]. Else arr[minInd[ind]+1..i] has sum greater than k. Compare its length with maximum length found so far. 

Implementation:




// CPP program to find largest subarray
// having sum greater than k.
#include <bits/stdc++.h>
using namespace std;
 
// Comparison function used to sort preSum vector.
bool compare(const pair<int, int>& a,
             const pair<int, int>& b)
{
    if (a.first == b.first)
        return a.second < b.second;
 
    return a.first < b.first;
}
 
// Function to find index in preSum vector upto which
// all prefix sum values are less than or equal to val.
int findInd(vector<pair<int, int> >& preSum, int n,
                                            int val)
{
 
    // Starting and ending index of search space.
    int l = 0;
    int h = n - 1;
    int mid;
 
    // To store required index value.
    int ans = -1;
 
    // If middle value is less than or equal to
    // val then index can lie in mid+1..n
    // else it lies in 0..mid-1.
    while (l <= h) {
        mid = (l + h) / 2;
        if (preSum[mid].first <= val) {
            ans = mid;
            l = mid + 1;
        }
        else
            h = mid - 1;
    }
 
    return ans;
}
 
// Function to find largest subarray having sum
// greater than or equal to k.
int largestSub(int arr[], int n, int k)
{
    int i;
 
    // Length of largest subarray.
    int maxlen = 0;
 
    // Vector to store pair of prefix sum
    // and corresponding ending index value.
    vector<pair<int, int> > preSum;
 
    // To store current value of prefix sum.
    int sum = 0;
 
    // To store minimum index value in range
    // 0..i of preSum vector.
    int minInd[n];
 
    // Insert values in preSum vector.
    for (i = 0; i < n; i++) {
        sum = sum + arr[i];
        preSum.push_back({ sum, i });
    }
 
    sort(preSum.begin(), preSum.end(), compare);
 
    // Update minInd array.
    minInd[0] = preSum[0].second;
 
    for (i = 1; i < n; i++) {
        minInd[i] = min(minInd[i - 1], preSum[i].second);
    }
 
    sum = 0;
    for (i = 0; i < n; i++) {
        sum = sum + arr[i];
 
        // If sum is greater than k, then answer
        // is i+1.
        if (sum > k)
            maxlen = i + 1;
 
        // If the sum is less than or equal to k, then
        // find if there is a prefix array having sum
        // that needs to be added to the current sum to
        // make its value greater than k. If yes, then
        // compare the length of updated subarray with
        // maximum length found so far.
        else {
            int ind = findInd(preSum, n, sum - k - 1);
            if (ind != -1 && minInd[ind] < i)
                maxlen = max(maxlen, i - minInd[ind]);
        }
    }
 
    return maxlen;
}
 
// Driver code.
int main()
{
    int arr[] = { -2, 1, 6, -3 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    int k = 5;
 
    cout << largestSub(arr, n, k);
    return 0;
}




// Java program to find largest subarray
// having sum greater than k.
 
import java.util.*;
 
// defining pair class
class pair {
  public int first;
  public int second;
 
  pair(int a, int b)
  {
    this.first = a;
    this.second = b;
  }
}
 
// implementing compare method
// to sort an array of pairs
class pairSort implements Comparator<pair> {
 
  public int compare(pair a, pair b)
  {
    if (a.first == b.first)
      return a.second - b.second;
 
    return a.first - b.first;
  }
}
 
class GFG {
 
  // Function to find index in preSum vector upto which
  // all prefix sum values are less than or equal to val.
  static int findInd(pair[] preSum, int n, int val)
  {
 
    // Starting and ending index of search space.
    int l = 0;
    int h = n - 1;
    int mid;
 
    // To store required index value.
    int ans = -1;
 
    // If middle value is less than or equal to
    // val then index can lie in mid+1..n
    // else it lies in 0..mid-1.
    while (l <= h) {
      mid = (l + h) / 2;
      if (preSum[mid].first <= val) {
        ans = mid;
        l = mid + 1;
      }
      else
        h = mid - 1;
    }
 
    return ans;
  }
  // Function to find largest subarray having sum
  // greater than or equal to k.
  static int largestSub(int arr[], int n, int k)
  {
    int i;
 
    // Length of largest subarray.
    int maxlen = 0;
 
    // Vector to store pair of prefix sum
    // and corresponding ending index value.
    pair[] preSum = new pair[n];
 
    // To store current value of prefix sum.
    int sum = 0;
 
    // To store minimum index value in range
    // 0..i of preSum vector.
    int[] minInd = new int[n];
 
    // Insert values in preSum vector.
    for (i = 0; i < n; i++) {
      sum = sum + arr[i];
      preSum[i] = new pair(sum, i);
    }
 
    Arrays.sort(preSum, new pairSort());
 
    // Update minInd array.
    minInd[0] = preSum[0].second;
 
    for (i = 1; i < n; i++) {
      minInd[i]
        = Math.min(minInd[i - 1], preSum[i].second);
    }
 
    sum = 0;
    for (i = 0; i < n; i++) {
      sum = sum + arr[i];
 
      // If sum is greater than k, then answer
      // is i+1.
      if (sum > k)
        maxlen = i + 1;
 
      // If the sum is less than or equal to k, then
      // find if there is a prefix array having sum
      // that needs to be added to the current sum to
      // make its value greater than k. If yes, then
      // compare the length of updated subarray with
      // maximum length found so far.
      else {
        int ind = findInd(preSum, n, sum - k - 1);
        if (ind != -1 && minInd[ind] < i)
          maxlen
          = Math.max(maxlen, i - minInd[ind]);
      }
    }
 
    return maxlen;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int arr[] = { -2, 1, 6, -3 };
    int n = arr.length;
 
    int k = 5;
 
    // Function call
    System.out.println(largestSub(arr, n, k));
  }
}
 
// This code is contributed by phasing17




# Python3 program to find largest subarray
# having sum greater than k.
 
# Comparison function used to
# sort preSum vector.
def compare(a, b):
 
    if a[0] == b[0]:
        return a[1] < b[1]
 
    return a[0] < b[0]
 
# Function to find index in preSum vector
# upto which all prefix sum values are less
# than or equal to val.
def findInd(preSum, n, val):
 
    # Starting and ending index of
    # search space.
    l, h = 0, n - 1
 
    # To store required index value.
    ans = -1
 
    # If middle value is less than or equal 
    # to val then index can lie in mid+1..n
    # else it lies in 0..mid-1.
    while l <= h:
        mid = (l + h) // 2
        if preSum[mid][0] <= val:
            ans = mid
            l = mid + 1
         
        else:
            h = mid - 1
 
    return ans
 
# Function to find largest subarray having
# sum greater than or equal to k.
def largestSub(arr, n, k):
 
    # Length of largest subarray.
    maxlen = 0
 
    # Vector to store pair of prefix sum
    # and corresponding ending index value.
    preSum = []
 
    # To store the current value of prefix sum.
    Sum = 0
 
    # To store minimum index value in range
    # 0..i of preSum vector.
    minInd = [None] * (n)
 
    # Insert values in preSum vector.
    for i in range(0, n):
        Sum = Sum + arr[i]
        preSum.append([Sum, i])
     
    preSum.sort()
     
    # Update minInd array.
    minInd[0] = preSum[0][1]
 
    for i in range(1, n):
        minInd[i] = min(minInd[i - 1],
                        preSum[i][1])
     
    Sum = 0
    for i in range(0, n):
        Sum = Sum + arr[i]
 
        # If sum is greater than k, then
        # answer is i+1.
        if Sum > k:
            maxlen = i + 1
 
        # If sum is less than or equal to k,
        # then find if there is a prefix array
        # having sum that needs to be added to
        # current sum to make its value greater
        # than k. If yes, then compare length
        # of updated subarray with maximum
        # length found so far.
        else:
            ind = findInd(preSum, n, Sum - k - 1)
            if ind != -1 and minInd[ind] < i:
                maxlen = max(maxlen, i - minInd[ind])
 
    return maxlen
 
# Driver code.
if __name__ == "__main__":
 
    arr = [-2, 1, 6, -3]
    n = len(arr)
 
    k = 5
 
    print(largestSub(arr, n, k))
     
# This code is contributed
# by Rituraj Jain




// C# program to find largest subarray
// having sum greater than k.
using System;
using System.Collections.Generic;
 
// defining pair class
class pair {
    public int first;
    public int second;
 
    public pair(int a, int b)
    {
        this.first = a;
        this.second = b;
    }
}
 
// implementing compare method
// to sort an array of pairs
class pairSort : Comparer<pair> {
 
    public override int Compare(pair a, pair b)
    {
        if (a.first == b.first)
            return a.second - b.second;
 
        return a.first - b.first;
    }
}
 
class GFG {
 
    // Function to find index in preSum vector upto which
    // all prefix sum values are less than or equal to val.
    static int findInd(pair[] preSum, int n, int val)
    {
 
        // Starting and ending index of search space.
        int l = 0;
        int h = n - 1;
        int mid;
 
        // To store required index value.
        int ans = -1;
 
        // If middle value is less than or equal to
        // val then index can lie in mid+1..n
        // else it lies in 0..mid-1.
        while (l <= h) {
            mid = (l + h) / 2;
            if (preSum[mid].first <= val) {
                ans = mid;
                l = mid + 1;
            }
            else
                h = mid - 1;
        }
 
        return ans;
    }
    // Function to find largest subarray having sum
    // greater than or equal to k.
    static int largestSub(int[] arr, int n, int k)
    {
        int i;
 
        // Length of largest subarray.
        int maxlen = 0;
 
        // Vector to store pair of prefix sum
        // and corresponding ending index value.
        pair[] preSum = new pair[n];
 
        // To store current value of prefix sum.
        int sum = 0;
 
        // To store minimum index value in range
        // 0..i of preSum vector.
        int[] minInd = new int[n];
 
        // Insert values in preSum vector.
        for (i = 0; i < n; i++) {
            sum = sum + arr[i];
            preSum[i] = new pair(sum, i);
        }
        Array.Sort(preSum, new pairSort());
 
        // Update minInd array.
        minInd[0] = preSum[0].second;
 
        for (i = 1; i < n; i++) {
            minInd[i]
                = Math.Min(minInd[i - 1], preSum[i].second);
        }
 
        sum = 0;
        for (i = 0; i < n; i++) {
            sum = sum + arr[i];
 
            // If sum is greater than k, then answer
            // is i+1.
            if (sum > k)
                maxlen = i + 1;
 
            // If the sum is less than or equal to k, then
            // find if there is a prefix array having sum
            // that needs to be added to the current sum to
            // make its value greater than k. If yes, then
            // compare the length of updated subarray with
            // maximum length found so far.
            else {
                int ind = findInd(preSum, n, sum - k - 1);
                if (ind != -1 && minInd[ind] < i)
                    maxlen
                        = Math.Max(maxlen, i - minInd[ind]);
            }
        }
 
        return maxlen;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int[] arr = { -2, 1, 6, -3 };
        int n = arr.Length;
 
        int k = 5;
 
        // Function call
        Console.WriteLine(largestSub(arr, n, k));
    }
}
 
// This code is contributed by phasing17




<script>
 
// JavaScript program to find largest subarray
// having sum greater than k.
 
// Comparison function used to
// sort preSum vector.
function compare(a, b){
 
    if(a[0] == b[0])
        return a[1] < b[1]
 
    return a[0] < b[0]
}
 
// Function to find index in preSum vector
// upto which all prefix sum values are less
// than or equal to val.
function findInd(preSum, n, val){
 
    // Starting and ending index of
    // search space.
    let l = 0;
    let h = n - 1;
 
    // To store required index value.
    let ans = -1;
 
    // If middle value is less than or equal
    // to val then index can lie in mid+1..n
    // else it lies in 0..mid-1.
    while(l <= h){
        mid = Math.floor((l + h) / 2)
        if(preSum[mid][0] <= val){
            ans = mid
            l = mid + 1
        }
         
        else h = mid - 1
    }
 
    return ans
}
 
// Function to find largest subarray having
// sum greater than or equal to k.
function largestSub(arr, n, k){
 
    // Length of largest subarray.
    let maxlen = 0
 
    // Vector to store pair of prefix sum
    // and corresponding ending index value.
    let preSum = []
 
    // To store the current value of prefix sum.
    let Sum = 0
 
    // To store minimum index value in range
    // 0..i of preSum vector.
    let minInd = new Array(n)
 
    // Insert values in preSum vector.
    for(let i = 0; i < n; i++){
        Sum = Sum + arr[i]
        preSum.push([Sum, i])
    }
     
    preSum.sort(compare)
     
    // Update minInd array.
    minInd[0] = preSum[0][1]
 
    for(let i = 1; i < n; i++){
        minInd[i] = Math.min(minInd[i - 1],
                        preSum[i][1])
    }
     
    Sum = 0
    for(let i = 0; i < n; i++)
    {
        Sum = Sum + arr[i]
 
        // If sum is greater than k, then
        // answer is i+1.
        if(Sum > k)
            maxlen = i + 1
 
        // If sum is less than or equal to k,
        // then find if there is a prefix array
        // having sum that needs to be added to
        // current sum to make its value greater
        // than k. If yes, then compare length
        // of updated subarray with maximum
        // length found so far.
        else{
            ind = findInd(preSum, n, Sum - k - 1)
            if(ind != -1 && minInd[ind] < i)
                maxlen = Math.max(maxlen, i - minInd[ind])
        }
    }
 
    return maxlen
 
}
 
// Driver code.
let    arr = [-2, 1, 6, -3]
let    n = arr.length
 
let    k = 5
 
document.write(largestSub(arr, n, k))
     
// This code is contributed by shinjanpatra
 
</script>

Output
2

Complexity Analysis:


Article Tags :