Smallest subarray with positive sum for all indices
Last Updated :
28 Feb, 2024
Given an array arr[] of size N. The task is to determine the minimum length of a subarray starting from index i, such that the sum of the subarray is strictly greater than 0. Calculate the length for all i’s in the range 1 to N. If no such subarray exists, then return 0.
Examples:
Input: N = 3, arr[] = {-4, 3, 4}
Output: {3, 1, 1}
Explanation: For index 0, we need to take the whole array for the sum to be positive, whereas for the other two indices taking only a single element makes the sum positive.
Input: N = 5, arr[] = {-2, -3, 5, -2, 1}
Output: {0, 2, 1, 0, 1}
Explanation: For indexes 0 and 3, no subarray with a positive sum exists.
Approach: To solve the problem, follow the below idea:
To find the minimum length of subarrays with sums greater than 0 for each index in the given array, use a prefix sum array and a stack to track the next greater element. Finding the next greater element in the prefix sum array will tell us the smallest length of subarray with positive sum.
It can be observed that for any index i, if the next greater element in the prefix sum array is at index j, then all the subarrays which start at index i and end at index < j will have negative sum.
Iterate through the array, updating the result array accordingly. The final result, excluding the last element, yields the desired lengths.
Step-by-step algorithm:
- Prefix Sum:
- Create an array (pref) where each element represents the cumulative sum of elements up to that index.
- Initialize:
- Set up a stack(s) to keep track of indices and initialize a result array (res).
- Find Length for First Element:
- Iterate from left to right in the array.
- If the prefix sum at an index is greater than 0, set the first element in the result array (res[0]) to the current index + 1.
- Next Greater Element:
- Iterate from right to left in the array.
- Use the stack to efficiently find the next greater element for each index.
- Update the result array based on the stack.
- Final Result:
- Remove the last element from the result array to get the final lengths.
Below is the implementation of the algorithm:
C++
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
vector< int > findAnswer( int N, vector< int >& arr) {
vector< long long > pref(N, arr[0]);
for ( int i = 1; i < N; i++) {
pref[i] = pref[i - 1] + arr[i];
}
stack< int > s;
vector< int > res(N + 1, 0);
for ( int i = 0; i < N; i++) {
if (pref[i] > 0) {
res[0] = i + 1;
break ;
}
}
for ( int i = N - 1; i >= 0; i--) {
while (!s.empty() && pref[s.top()] <= pref[i])
s.pop();
if (s.empty())
res[i + 1] = 0;
else if (i < N - 1)
res[i + 1] = s.top() - i;
s.push(i);
}
res.pop_back();
return res;
}
int main() {
vector< int > arr = { -2, -3, 5, -2, 1 };
int N = arr.size();
vector< int > ans = findAnswer(N, arr);
for ( auto a : ans) {
cout << a << " " ;
}
return 0;
}
|
Java
import java.util.*;
public class Solution {
static List<Integer> findAnswer( int N, List<Integer> arr) {
List<Long> pref = new ArrayList<>(Collections.nCopies(N, 0L));
pref.set( 0 , ( long ) arr.get( 0 ));
for ( int i = 1 ; i < N; i++) {
pref.set(i, pref.get(i - 1 ) + arr.get(i));
}
Stack<Integer> s = new Stack<>();
List<Integer> res = new ArrayList<>(Collections.nCopies(N + 1 , 0 ));
for ( int i = 0 ; i < N; i++) {
if (pref.get(i) > 0 ) {
res.set( 0 , i + 1 );
break ; }
}
for ( int i = N - 1 ; i >= 0 ; i--) {
while (!s.isEmpty() && pref.get(s.peek()) <= pref.get(i))
s.pop();
if (s.isEmpty())
res.set(i + 1 , 0 );
else if (i < N - 1 )
res.set(i + 1 , s.peek() - i);
s.push(i);
}
res.remove(res.size() - 1 );
return res;
}
public static void main(String[] args) {
List<Integer> arr = Arrays.asList(- 2 , - 3 , 5 , - 2 , 1 );
int N = arr.size();
List<Integer> ans = findAnswer(N, arr);
for ( int a : ans) {
System.out.print(a + " " );
}
}
}
|
Python3
def findAnswer(N, arr):
pref = [arr[ 0 ]] * N
for i in range ( 1 , N):
pref[i] = pref[i - 1 ] + arr[i]
s = []
res = [ 0 ] * (N + 1 )
for i in range (N):
if pref[i] > 0 :
res[ 0 ] = i + 1
break
for i in range (N - 1 , - 1 , - 1 ):
while s and pref[s[ - 1 ]] < = pref[i]:
s.pop()
if not s:
res[i + 1 ] = 0
elif i < N - 1 :
res[i + 1 ] = s[ - 1 ] - i
s.append(i)
res.pop()
return res
arr = [ - 2 , - 3 , 5 , - 2 , 1 ]
N = len (arr)
ans = findAnswer(N, arr)
for a in ans:
print (a, end = " " )
|
C#
using System;
using System.Collections.Generic;
public class Solution {
static List< int > FindAnswer( int N, List< int > arr)
{
List< long > pref = new List< long >( new long [N]);
pref[0] = arr[0];
for ( int i = 1; i < N; i++) {
pref[i] = pref[i - 1] + arr[i];
}
Stack< int > s = new Stack< int >();
List< int > res = new List< int >( new int [N + 1]);
for ( int i = 0; i < N; i++) {
if (pref[i] > 0) {
res[0] = i + 1;
break ;
}
}
for ( int i = N - 1; i >= 0; i--) {
while (s.Count > 0 && pref[s.Peek()] <= pref[i])
s.Pop();
if (s.Count == 0)
res[i + 1] = 0;
else if (i < N - 1)
res[i + 1] = s.Peek() - i;
s.Push(i);
}
res.RemoveAt(N);
return res;
}
public static void Main( string [] args)
{
List< int > arr
= new List< int >() { -2, -3, 5, -2, 1 };
int N = arr.Count;
List< int > ans = FindAnswer(N, arr);
foreach ( var a in ans) { Console.Write(a + " " ); }
}
}
|
Javascript
function findAnswer(arr) {
const N = arr.length;
const pref = new Array(N).fill(arr[0]);
for (let i = 1; i < N; i++) {
pref[i] = pref[i - 1] + arr[i];
}
const s = [];
const res = new Array(N + 1).fill(0);
for (let i = 0; i < N; i++) {
if (pref[i] > 0) {
res[0] = i + 1;
break ;
}
}
for (let i = N - 1; i >= 0; i--) {
while (s.length && pref[s[s.length - 1]] <= pref[i]) {
s.pop();
}
if (!s.length) {
res[i + 1] = 0;
} else if (i < N - 1) {
res[i + 1] = s[s.length - 1] - i;
}
s.push(i);
}
res.pop();
return res;
}
const arr = [-2, -3, 5, -2, 1];
const ans = findAnswer(arr);
console.log(ans.join( " " ));
|
Time Complexity: O(N), where N is the length of input array arr[].
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...