Open In App

Find the Sub-array with sum closest to 0

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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++




// C++ program to find subarray with
// sum closest to 0
#include <bits/stdc++.h>
using namespace std;
  
// Function to find the subarray
pair<int, int> findSubArray(int arr[], int n)
{
  
    int start, end, min_sum = INT_MAX;
  
    // Pick a starting point
    for (int i = 0; i < n; i++) {
  
        // Consider current starting point
        // as a subarray and update minimum
        // sum and subarray indexes
        int curr_sum = arr[i];
        if (min_sum > abs(curr_sum)) {
            min_sum = abs(curr_sum);
            start = i;
            end = i;
        }
  
        // Try all subarrays starting with i
        for (int j = i + 1; j < n; j++) {
            curr_sum = curr_sum + arr[j];
  
            // update minimum sum
            // and subarray indexes
            if (min_sum > abs(curr_sum)) {
                min_sum = abs(curr_sum);
                start = i;
                end = j;
            }
        }
    }
  
    // Return starting and ending indexes
    pair<int, int> p = make_pair(start, end);
    return p;
}
  
// Drivers code
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




// Java program to find subarray with
// sum closest to 0
  
class GFG
{
  
    static class Pair 
    {
  
        int first, second;
        public Pair(int first, int second)
        {
            this.first = first;
            this.second = second;
        }
  
    }
      
    // Function to find the subarray
    static Pair findSubArray(int arr[], int n)
    {
  
        int start = 0, end = 0, min_sum = Integer.MAX_VALUE;
  
        // Pick a starting point
        for (int i = 0; i < n; i++)
        {
  
            // Consider current starting point
            // as a subarray and update minimum
            // sum and subarray indexes
            int curr_sum = arr[i];
            if (min_sum > Math.abs(curr_sum)) 
            {
                min_sum = Math.abs(curr_sum);
                start = i;
                end = i;
            }
  
            // Try all subarrays starting with i
            for (int j = i + 1; j < n; j++) 
            {
                curr_sum = curr_sum + arr[j];
  
                // update minimum sum
                // and subarray indexes
                if (min_sum > Math.abs(curr_sum)) 
                {
                    min_sum = Math.abs(curr_sum);
                    start = i;
                    end = j;
                }
            }
        }
  
        // Return starting and ending indexes
        Pair p = new Pair(start, end);
        return p;
    }
  
    // Drivers code
    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);
    }
}
  
// This code has been contributed by 29AjayKumar


Python3




# Python 3 program to find subarray with
# sum closest to 0
import sys
  
# Function to find the subarray
def findSubArray(arr, n):
    min_sum = sys.maxsize
  
    # Pick a starting point
    for i in range(n):
          
        # Consider current starting point
        # as a subarray and update minimum
        # sum and subarray indexes
        curr_sum = arr[i]
        if (min_sum > abs(curr_sum)):
            min_sum = abs(curr_sum)
            start = i
            end = i
  
        # Try all subarrays starting with i
        for j in range(i + 1, n, 1):
            curr_sum = curr_sum + arr[j]
  
            # update minimum sum
            # and subarray indexes
            if (min_sum > abs(curr_sum)):
                min_sum = abs(curr_sum)
                start = i
                end = j
  
    # Return starting and ending indexes
    p = [start, end]
    return p
  
# Driver Code
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])
  
# This code is contributed by
# Surendra_Gangwar


C#




// C# program to find subarray with
// sum closest to 0
using System;
      
class GFG
{
  
    public class Pair 
    {
  
        public int first, second;
        public Pair(int first, int second)
        {
            this.first = first;
            this.second = second;
        }
  
    }
      
    // Function to find the subarray
    static Pair findSubArray(int []arr, int n)
    {
  
        int start = 0, end = 0, min_sum = int.MaxValue;
  
        // Pick a starting point
        for (int i = 0; i < n; i++)
        {
  
            // Consider current starting point
            // as a subarray and update minimum
            // sum and subarray indexes
            int curr_sum = arr[i];
            if (min_sum > Math.Abs(curr_sum)) 
            {
                min_sum = Math.Abs(curr_sum);
                start = i;
                end = i;
            }
  
            // Try all subarrays starting with i
            for (int j = i + 1; j < n; j++) 
            {
                curr_sum = curr_sum + arr[j];
  
                // update minimum sum
                // and subarray indexes
                if (min_sum > Math.Abs(curr_sum)) 
                {
                    min_sum = Math.Abs(curr_sum);
                    start = i;
                    end = j;
                }
            }
        }
  
        // Return starting and ending indexes
        Pair p = new Pair(start, end);
        return p;
    }
  
    // Drivers code
    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);
    }
}
  
// This code is contributed by Princi Singh


Javascript




<script>
  
// JavaScript program to find subarray with
// sum closest to 0
  
// Function to find the subarray
function findSubArray(arr, n) {
  
    let start, end, min_sum = Number.MAX_SAFE_INTEGER;
  
    // Pick a starting point
    for (let i = 0; i < n; i++) {
  
        // Consider current starting point
        // as a subarray and update minimum
        // sum and subarray indexes
        let curr_sum = arr[i];
        if (min_sum > Math.abs(curr_sum)) {
            min_sum = Math.abs(curr_sum);
            start = i;
            end = i;
        }
  
        // Try all subarrays starting with i
        for (let j = i + 1; j < n; j++) {
            curr_sum = curr_sum + arr[j];
  
            // update minimum sum
            // and subarray indexes
            if (min_sum > Math.abs(curr_sum)) {
                min_sum = Math.abs(curr_sum);
                start = i;
                end = j;
            }
        }
    }
  
    // Return starting and ending indexes
    let p = [start, end];
    return p;
}
  
// Drivers code
  
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++




// C++ program to find subarray with sum 
// closest to 0
#include <bits/stdc++.h>
using namespace std;
  
struct prefix {
    int sum;
    int index;
};
  
// Sort on the basis of sum
bool comparison(prefix a, prefix b)
{
    return a.sum < b.sum;
}
  
// Returns subarray with sum closest to 0. 
pair<int, int> findSubArray(int arr[], int n)
{
    int start, end, min_diff = INT_MAX;
  
    prefix pre_sum[n + 1];
  
    // To consider the case of subarray starting
    // from beginning of the array
    pre_sum[0].sum = 0;
    pre_sum[0].index = -1;
  
    // Store prefix sum with index
    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 on the basis of sum
    sort(pre_sum, pre_sum + (n + 1), comparison);
  
    // Find two consecutive elements with minimum difference
    for (int i = 1; i <= n; i++) {
        int diff = pre_sum[i].sum - pre_sum[i-1].sum;
  
        // Update minimum difference
        // and starting and ending indexes
        if (min_diff > diff) {
            min_diff = diff;
            start = pre_sum[i-1].index;
            end = pre_sum[i].index;
        }
    }
  
    // Return starting and ending indexes
    pair<int, int> p = make_pair(start + 1, end);
    return p;
}
  
// Drivers code
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




// Java program to find subarray with sum
// closest to 0
import java.util.*;
  
class Prefix 
{
    int sum, index;
}
  
class Pair
{
    int first, second;
    Pair(int a, int b)
    {
        first = a;
        second = b;
    }
}
  
class GFG{
  
// Returns subarray with sum closest to 0.
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();
          
    // To consider the case of subarray starting
    // from beginning of the array
    pre_sum[0].sum = 0;
    pre_sum[0].index = -1;
  
    // Store prefix sum with index
    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 on the basis of sum
    Arrays.sort(pre_sum, ((a, b) -> a.sum - b.sum));
  
    // Find two consecutive elements with minimum
    // difference
    for(int i = 1; i <= n; i++) 
    {
        int diff = pre_sum[i].sum - 
                   pre_sum[i - 1].sum;
  
        // Update minimum difference
        // and starting and ending indexes
        if (min_diff > diff)
        {
            min_diff = diff;
            start = pre_sum[i - 1].index;
            end = pre_sum[i].index;
        }
    }
  
    // Return starting and ending indexes
    Pair p = new Pair(start + 1, end);
    return p;
}
  
// Driver code
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);
}
}
  
// This code is contributed by jrishabh99


Python3




# Python3 program to find subarray 
# with sum closest to 0 
class prefix:
      
    def __init__(self, sum, index):
        self.sum = sum
        self.index = index
  
# Returns subarray with sum closest to 0. 
def findSubArray(arr, n): 
  
    start, end, min_diff = None, None, float('inf'
  
    pre_sum = [None] * (n + 1)
  
    # To consider the case of subarray 
    # starting from beginning of the array 
    pre_sum[0] = prefix(0, -1)
  
    # Store prefix sum with index 
    for i in range(1, n + 1): 
        pre_sum[i] = prefix(pre_sum[i - 1].sum + 
                                arr[i - 1], i - 1
  
    # Sort on the basis of sum 
    pre_sum.sort(key = lambda x: x.sum)
  
    # Find two consecutive elements 
    # with minimum difference 
    for i in range(1, n + 1): 
        diff = pre_sum[i].sum - pre_sum[i - 1].sum
  
        # Update minimum difference 
        # and starting and ending indexes 
        if min_diff > diff: 
            min_diff = diff 
            start = pre_sum[i - 1].index 
            end = pre_sum[i].index 
          
    # Return starting and ending indexes 
    return (start + 1, end) 
  
# Driver code 
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]) 
  
# This code is contributed by Rituraj Jain


C#




// C# program to find subarray with sum
// closest to 0
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{
  
// Returns subarray with sum closest to 0.
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();
          
    // To consider the case of subarray starting
    // from beginning of the array
    pre_sum[0].sum = 0;
    pre_sum[0].index = -1;
  
    // Store prefix sum with index
    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 on the basis of sum
    Array.Sort(pre_sum);
  
    // Find two consecutive elements with minimum
    // difference
    for(int i = 1; i <= n; i++) 
    {
        int diff = pre_sum[i].sum - 
                   pre_sum[i - 1].sum;
  
        // Update minimum difference
        // and starting and ending indexes
        if (min_diff > diff)
        {
            min_diff = diff;
            start = pre_sum[i - 1].index;
            end = pre_sum[i].index;
        }
    }
  
    // Return starting and ending indexes
    Pair p = new Pair(start + 1, end);
    return p;
}
  
// Driver code
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);
}
}
  
// This code is contributed by 29AjayKumar


Javascript




<script>
// Javascript program to find subarray with sum
// closest to 0
class Prefix 
{
    constructor()
    {
        this.sum = 0;
        this.index = 0;
    }
}
  
class Pair
{
    constructor(a, b)
    {
        this.first = a;
        this.second = b;
    }
}
  
// Returns subarray with sum closest to 0.
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();
            
    // To consider the case of subarray starting
    // from beginning of the array
    pre_sum[0].sum = 0;
    pre_sum[0].index = -1;
    
    // Store prefix sum with index
    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;
    }
    
    // Sort on the basis of sum
    pre_sum.sort(function(a, b) {return a.sum - b.sum});
    
    // Find two consecutive elements with minimum
    // difference
    for(let i = 1; i <= n; i++) 
    {
        let diff = pre_sum[i].sum - 
                   pre_sum[i - 1].sum;
    
        // Update minimum difference
        // and starting and ending indexes
        if (min_diff > diff)
        {
            min_diff = diff;
            start = pre_sum[i - 1].index;
            end = pre_sum[i].index;
        }
    }
    
    // Return starting and ending indexes
    let p = new Pair(start + 1, end);
    return p;
}
  
// Driver code
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);
  
// This code is contributed by rag2127
</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.

 



Last Updated : 15 Sep, 2023
Like Article
Save Article
Share your thoughts in the comments
Similar Reads