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:
C++
#include <bits/stdc++.h>
using namespace std;
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;
}
int findInd(vector<pair< int , int > >& preSum, int n,
int val)
{
int l = 0;
int h = n - 1;
int mid;
int ans = -1;
while (l <= h) {
mid = (l + h) / 2;
if (preSum[mid].first <= val) {
ans = mid;
l = mid + 1;
}
else
h = mid - 1;
}
return ans;
}
int largestSub( int arr[], int n, int k)
{
int i;
int maxlen = 0;
vector<pair< int , int > > preSum;
int sum = 0;
int minInd[n];
for (i = 0; i < n; i++) {
sum = sum + arr[i];
preSum.push_back({ sum, i });
}
sort(preSum.begin(), preSum.end(), compare);
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 > k)
maxlen = i + 1;
else {
int ind = findInd(preSum, n, sum - k - 1);
if (ind != -1 && minInd[ind] < i)
maxlen = max(maxlen, i - minInd[ind]);
}
}
return maxlen;
}
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
import java.util.*;
class pair {
public int first;
public int second;
pair( int a, int b)
{
this .first = a;
this .second = b;
}
}
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 {
static int findInd(pair[] preSum, int n, int val)
{
int l = 0 ;
int h = n - 1 ;
int mid;
int ans = - 1 ;
while (l <= h) {
mid = (l + h) / 2 ;
if (preSum[mid].first <= val) {
ans = mid;
l = mid + 1 ;
}
else
h = mid - 1 ;
}
return ans;
}
static int largestSub( int arr[], int n, int k)
{
int i;
int maxlen = 0 ;
pair[] preSum = new pair[n];
int sum = 0 ;
int [] minInd = new int [n];
for (i = 0 ; i < n; i++) {
sum = sum + arr[i];
preSum[i] = new pair(sum, i);
}
Arrays.sort(preSum, new pairSort());
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 > k)
maxlen = i + 1 ;
else {
int ind = findInd(preSum, n, sum - k - 1 );
if (ind != - 1 && minInd[ind] < i)
maxlen
= Math.max(maxlen, i - minInd[ind]);
}
}
return maxlen;
}
public static void main(String[] args)
{
int arr[] = { - 2 , 1 , 6 , - 3 };
int n = arr.length;
int k = 5 ;
System.out.println(largestSub(arr, n, k));
}
}
|
Python3
def compare(a, b):
if a[ 0 ] = = b[ 0 ]:
return a[ 1 ] < b[ 1 ]
return a[ 0 ] < b[ 0 ]
def findInd(preSum, n, val):
l, h = 0 , n - 1
ans = - 1
while l < = h:
mid = (l + h) / / 2
if preSum[mid][ 0 ] < = val:
ans = mid
l = mid + 1
else :
h = mid - 1
return ans
def largestSub(arr, n, k):
maxlen = 0
preSum = []
Sum = 0
minInd = [ None ] * (n)
for i in range ( 0 , n):
Sum = Sum + arr[i]
preSum.append([ Sum , i])
preSum.sort()
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 > k:
maxlen = i + 1
else :
ind = findInd(preSum, n, Sum - k - 1 )
if ind ! = - 1 and minInd[ind] < i:
maxlen = max (maxlen, i - minInd[ind])
return maxlen
if __name__ = = "__main__" :
arr = [ - 2 , 1 , 6 , - 3 ]
n = len (arr)
k = 5
print (largestSub(arr, n, k))
|
C#
using System;
using System.Collections.Generic;
class pair {
public int first;
public int second;
public pair( int a, int b)
{
this .first = a;
this .second = b;
}
}
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 {
static int findInd(pair[] preSum, int n, int val)
{
int l = 0;
int h = n - 1;
int mid;
int ans = -1;
while (l <= h) {
mid = (l + h) / 2;
if (preSum[mid].first <= val) {
ans = mid;
l = mid + 1;
}
else
h = mid - 1;
}
return ans;
}
static int largestSub( int [] arr, int n, int k)
{
int i;
int maxlen = 0;
pair[] preSum = new pair[n];
int sum = 0;
int [] minInd = new int [n];
for (i = 0; i < n; i++) {
sum = sum + arr[i];
preSum[i] = new pair(sum, i);
}
Array.Sort(preSum, new pairSort());
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 > k)
maxlen = i + 1;
else {
int ind = findInd(preSum, n, sum - k - 1);
if (ind != -1 && minInd[ind] < i)
maxlen
= Math.Max(maxlen, i - minInd[ind]);
}
}
return maxlen;
}
public static void Main( string [] args)
{
int [] arr = { -2, 1, 6, -3 };
int n = arr.Length;
int k = 5;
Console.WriteLine(largestSub(arr, n, k));
}
}
|
Javascript
<script>
function compare(a, b){
if (a[0] == b[0])
return a[1] < b[1]
return a[0] < b[0]
}
function findInd(preSum, n, val){
let l = 0;
let h = n - 1;
let ans = -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 largestSub(arr, n, k){
let maxlen = 0
let preSum = []
let Sum = 0
let minInd = new Array(n)
for (let i = 0; i < n; i++){
Sum = Sum + arr[i]
preSum.push([Sum, i])
}
preSum.sort(compare)
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 > k)
maxlen = i + 1
else {
ind = findInd(preSum, n, Sum - k - 1)
if (ind != -1 && minInd[ind] < i)
maxlen = Math.max(maxlen, i - minInd[ind])
}
}
return maxlen
}
let arr = [-2, 1, 6, -3]
let n = arr.length
let k = 5
document.write(largestSub(arr, n, k))
</script>
|
Complexity Analysis:
- Time Complexity: O(nlogn)
- Auxiliary Space: O(n)
Last Updated :
30 Aug, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...