Find the Sub-array with sum closest to 0
Last Updated :
15 Sep, 2023
Given an array of both positive and negative numbers, the task is to find out the subarray whose sum is closest to 0.
There can be multiple such subarrays, we need to output just 1 of them.
Examples:
Input : arr[] = {-1, 3, 2, -5, 4}
Output : 1, 3
Subarray from index 1 to 3 has sum closest to 0 i.e.
3 + 2 + -5 = 0
Input : {2, -5, 4, -6, 3}
Output : 0, 2
2 + -5 + 4 = 1 closest to 0
Asked in : Microsoft
A Naive approach is to consider all subarrays one by one and update indexes of subarray with sum closest to 0.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
pair< int , int > findSubArray( int arr[], int n)
{
int start, end, min_sum = INT_MAX;
for ( int i = 0; i < n; i++) {
int curr_sum = arr[i];
if (min_sum > abs (curr_sum)) {
min_sum = abs (curr_sum);
start = i;
end = i;
}
for ( int j = i + 1; j < n; j++) {
curr_sum = curr_sum + arr[j];
if (min_sum > abs (curr_sum)) {
min_sum = abs (curr_sum);
start = i;
end = j;
}
}
}
pair< int , int > p = make_pair(start, end);
return p;
}
int main()
{
int arr[] = { 2, -5, 4, -6, -3 };
int n = sizeof (arr) / sizeof (arr[0]);
pair< int , int > point = findSubArray(arr, n);
cout << "Subarray starting from " ;
cout << point.first << " to " << point.second;
return 0;
}
|
Java
class GFG
{
static class Pair
{
int first, second;
public Pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
static Pair findSubArray( int arr[], int n)
{
int start = 0 , end = 0 , min_sum = Integer.MAX_VALUE;
for ( int i = 0 ; i < n; i++)
{
int curr_sum = arr[i];
if (min_sum > Math.abs(curr_sum))
{
min_sum = Math.abs(curr_sum);
start = i;
end = i;
}
for ( int j = i + 1 ; j < n; j++)
{
curr_sum = curr_sum + arr[j];
if (min_sum > Math.abs(curr_sum))
{
min_sum = Math.abs(curr_sum);
start = i;
end = j;
}
}
}
Pair p = new Pair(start, end);
return p;
}
public static void main(String[] args)
{
int arr[] = { 2 , - 5 , 4 , - 6 , - 3 };
int n = arr.length;
Pair point = findSubArray(arr, n);
System.out.println( "Subarray starting from "
+ point.first + " to " + point.second);
}
}
|
Python3
import sys
def findSubArray(arr, n):
min_sum = sys.maxsize
for i in range (n):
curr_sum = arr[i]
if (min_sum > abs (curr_sum)):
min_sum = abs (curr_sum)
start = i
end = i
for j in range (i + 1 , n, 1 ):
curr_sum = curr_sum + arr[j]
if (min_sum > abs (curr_sum)):
min_sum = abs (curr_sum)
start = i
end = j
p = [start, end]
return p
if __name__ = = '__main__' :
arr = [ 2 , - 5 , 4 , - 6 , - 3 ]
n = len (arr)
point = findSubArray(arr, n)
print ( "Subarray starting from " , end = "")
print (point[ 0 ], "to" , point[ 1 ])
|
C#
using System;
class GFG
{
public class Pair
{
public int first, second;
public Pair( int first, int second)
{
this .first = first;
this .second = second;
}
}
static Pair findSubArray( int []arr, int n)
{
int start = 0, end = 0, min_sum = int .MaxValue;
for ( int i = 0; i < n; i++)
{
int curr_sum = arr[i];
if (min_sum > Math.Abs(curr_sum))
{
min_sum = Math.Abs(curr_sum);
start = i;
end = i;
}
for ( int j = i + 1; j < n; j++)
{
curr_sum = curr_sum + arr[j];
if (min_sum > Math.Abs(curr_sum))
{
min_sum = Math.Abs(curr_sum);
start = i;
end = j;
}
}
}
Pair p = new Pair(start, end);
return p;
}
public static void Main(String[] args)
{
int []arr = {2, -5, 4, -6, -3};
int n = arr.Length;
Pair point = findSubArray(arr, n);
Console.WriteLine( "Subarray starting from "
+ point.first + " to " + point.second);
}
}
|
Javascript
<script>
function findSubArray(arr, n) {
let start, end, min_sum = Number.MAX_SAFE_INTEGER;
for (let i = 0; i < n; i++) {
let curr_sum = arr[i];
if (min_sum > Math.abs(curr_sum)) {
min_sum = Math.abs(curr_sum);
start = i;
end = i;
}
for (let j = i + 1; j < n; j++) {
curr_sum = curr_sum + arr[j];
if (min_sum > Math.abs(curr_sum)) {
min_sum = Math.abs(curr_sum);
start = i;
end = j;
}
}
}
let p = [start, end];
return p;
}
let arr = [2, -5, 4, -6, -3];
let n = arr.length;
let point = findSubArray(arr, n);
document.write( "Subarray starting from " );
document.write(point[0] + " to " + point[1]);
</script>
|
Output
Subarray starting from 0 to 2
Time Complexity: O(n2)
Space Complexity: O(1) as no extra space has been used.
An Efficient method is to perform following steps:-
- Maintain a Prefix sum array . Also maintain indexes in the prefix sum array.
- Sort the prefix sum array on the basis of sum.
- Find the two elements in a prefix sum array with minimum difference.
i.e. Find min(pre_sum[i] - pre_sum[i-1])
- Return indexes of pre_sum with minimum difference.
- Subarray with (lower_index+1, upper_index) will have the sum closest to 0.
- Taking lower_index+1 because on subtracting value at lower_index we get the sum closest to 0. That’s why lower_index need not to be included.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
struct prefix {
int sum;
int index;
};
bool comparison(prefix a, prefix b)
{
return a.sum < b.sum;
}
pair< int , int > findSubArray( int arr[], int n)
{
int start, end, min_diff = INT_MAX;
prefix pre_sum[n + 1];
pre_sum[0].sum = 0;
pre_sum[0].index = -1;
for ( int i = 1; i <= n; i++) {
pre_sum[i].sum = pre_sum[i-1].sum + arr[i-1];
pre_sum[i].index = i - 1;
}
sort(pre_sum, pre_sum + (n + 1), comparison);
for ( int i = 1; i <= n; i++) {
int diff = pre_sum[i].sum - pre_sum[i-1].sum;
if (min_diff > diff) {
min_diff = diff;
start = pre_sum[i-1].index;
end = pre_sum[i].index;
}
}
pair< int , int > p = make_pair(start + 1, end);
return p;
}
int main()
{
int arr[] = { 2, 3, -4, -1, 6 };
int n = sizeof (arr) / sizeof (arr[0]);
pair< int , int > point = findSubArray(arr, n);
cout << "Subarray starting from " ;
cout << point.first << " to " << point.second;
return 0;
}
|
Java
import java.util.*;
class Prefix
{
int sum, index;
}
class Pair
{
int first, second;
Pair( int a, int b)
{
first = a;
second = b;
}
}
class GFG{
static Pair findSubArray( int arr[], int n)
{
int start = - 1 , end = - 1 ,
min_diff = Integer.MAX_VALUE;
Prefix pre_sum[] = new Prefix[n + 1 ];
for ( int i = 0 ; i < n + 1 ; i++)
pre_sum[i] = new Prefix();
pre_sum[ 0 ].sum = 0 ;
pre_sum[ 0 ].index = - 1 ;
for ( int i = 1 ; i <= n; i++)
{
pre_sum[i].sum = pre_sum[i - 1 ].sum +
arr[i - 1 ];
pre_sum[i].index = i - 1 ;
}
Arrays.sort(pre_sum, ((a, b) -> a.sum - b.sum));
for ( int i = 1 ; i <= n; i++)
{
int diff = pre_sum[i].sum -
pre_sum[i - 1 ].sum;
if (min_diff > diff)
{
min_diff = diff;
start = pre_sum[i - 1 ].index;
end = pre_sum[i].index;
}
}
Pair p = new Pair(start + 1 , end);
return p;
}
public static void main(String[] args)
{
int arr[] = { 2 , 3 , - 4 , - 1 , 6 };
int n = arr.length;
Pair point = findSubArray(arr, n);
System.out.print( "Subarray starting from " );
System.out.println(point.first + " to " +
point.second);
}
}
|
Python3
class prefix:
def __init__( self , sum , index):
self . sum = sum
self .index = index
def findSubArray(arr, n):
start, end, min_diff = None , None , float ( 'inf' )
pre_sum = [ None ] * (n + 1 )
pre_sum[ 0 ] = prefix( 0 , - 1 )
for i in range ( 1 , n + 1 ):
pre_sum[i] = prefix(pre_sum[i - 1 ]. sum +
arr[i - 1 ], i - 1 )
pre_sum.sort(key = lambda x: x. sum )
for i in range ( 1 , n + 1 ):
diff = pre_sum[i]. sum - pre_sum[i - 1 ]. sum
if min_diff > diff:
min_diff = diff
start = pre_sum[i - 1 ].index
end = pre_sum[i].index
return (start + 1 , end)
if __name__ = = "__main__" :
arr = [ 2 , 3 , - 4 , - 1 , 6 ]
n = len (arr)
point = findSubArray(arr, n)
print ( "Subarray starting from" ,
point[ 0 ], "to" , point[ 1 ])
|
C#
using System;
class Prefix : IComparable<Prefix>
{
public int sum, index;
public int CompareTo(Prefix p)
{
return this .sum-p.sum;
}
}
class Pair
{
public int first, second;
public Pair( int a, int b)
{
first = a;
second = b;
}
}
public class GFG{
static Pair findSubArray( int []arr, int n)
{
int start = -1, end = -1,
min_diff = int .MaxValue;
Prefix []pre_sum = new Prefix[n + 1];
for ( int i = 0; i < n + 1; i++)
pre_sum[i] = new Prefix();
pre_sum[0].sum = 0;
pre_sum[0].index = -1;
for ( int i = 1; i <= n; i++)
{
pre_sum[i].sum = pre_sum[i - 1].sum +
arr[i - 1];
pre_sum[i].index = i - 1;
}
Array.Sort(pre_sum);
for ( int i = 1; i <= n; i++)
{
int diff = pre_sum[i].sum -
pre_sum[i - 1].sum;
if (min_diff > diff)
{
min_diff = diff;
start = pre_sum[i - 1].index;
end = pre_sum[i].index;
}
}
Pair p = new Pair(start + 1, end);
return p;
}
public static void Main(String[] args)
{
int []arr = { 2, 3, -4, -1, 6 };
int n = arr.Length;
Pair point = findSubArray(arr, n);
Console.Write( "Subarray starting from " );
Console.WriteLine(point.first + " to " +
point.second);
}
}
|
Javascript
<script>
class Prefix
{
constructor()
{
this .sum = 0;
this .index = 0;
}
}
class Pair
{
constructor(a, b)
{
this .first = a;
this .second = b;
}
}
function findSubArray(arr, n)
{
let start = -1, end = -1,
min_diff = Number.MAX_VALUE;
let pre_sum = new Array(n + 1);
for (let i = 0; i < n + 1; i++)
pre_sum[i] = new Prefix();
pre_sum[0].sum = 0;
pre_sum[0].index = -1;
for (let i = 1; i <= n; i++)
{
pre_sum[i].sum = pre_sum[i - 1].sum +
arr[i - 1];
pre_sum[i].index = i - 1;
}
pre_sum.sort( function (a, b) { return a.sum - b.sum});
for (let i = 1; i <= n; i++)
{
let diff = pre_sum[i].sum -
pre_sum[i - 1].sum;
if (min_diff > diff)
{
min_diff = diff;
start = pre_sum[i - 1].index;
end = pre_sum[i].index;
}
}
let p = new Pair(start + 1, end);
return p;
}
let arr = [2, 3, -4, -1, 6 ];
let n = arr.length;
let point = findSubArray(arr, n);
document.write( "Subarray starting from " );
document.write(point.first + " to " +
point.second);
</script>
|
Output
Subarray starting from 0 to 3
Time Complexity: O(n log n)
Space Complexity: O(n) as pre_sum array has been created. Here, n is size of input array.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...