Subarray whose sum is closest to K

14 Jun, 2022
Given an array of positive and negative integers and an integer K. The task is to find the subarray which has its sum closest to k. In case of multiple answers, print anyone. 
Note: Closest here means abs(sum-k) should be minimal. 
Examples: 
Input: a[] = { -5, 12, -3, 4, -15, 6, 1 }, K = 2 Output: 1 The subarray {-3, 4} or {1} has sum = 1 which is the closest to K.
Input: a[] = { 2, 2, -1, 5, -3, -2 }, K = 7 Output: 6 Here the output can be 6 or 8 The subarray {2, 2, -1, 5} gives sum as 8 which has abs(8-7) = 1 which is same as that of the subarray {2, -1, 5} which has abs(6-7) = 1. 
A naive approach is to check for all possible subarray sum using prefix sum. The complexity in that case will be O(N2).
An efficient solution will be to use C++ STL set and binary search to solve the following problem. Follow the below algorithm to solve the above problem. 
Initially insert the first element in the set container.
Initialize the answer sum as first element and difference as abs(A0-k).
Iterate for all array elements from 1 to N and keep adding the elements to prefix sum at each step to the set container.
At every iteration, since the prefix sum is already there, we just need to subtract the sum of some elements from beginning to get the sum of any subarray. The greedy way will be to subtract the sum of the subarray which takes the sum closest to K.
Using binary search (lower_bound() function can be used) find the sum of subarray from beginning which is closest to (prefix-k) as the subtraction of that number from prefix sum will give the subarray sum which is closest to K till that iteration.
Also check for the index before which lower_bound() returns, since the sum can either be greater or lesser than K.
If the lower_bound returns no such element, then the current prefix sum is compared and updated if it was lesser than the previous computed sum.
Below is the implementation of the above approach. 
C++
Java
Python3
C#
Javascript
// C++ program to find the// sum of subarray whose sum is// closest to K#include <bits/stdc++.h>using namespace std; // Function to find the sum of subarray// whose sum is closest to Kint closestSubarraySumToK(int a[], int n, int k){     // Declare a set    set<int> s;     // initially consider the    // first subarray as the first    // element in the array    int presum = a[0];     // insert    s.insert(a[0]);     // Initially let this difference    // be the minimum    int mini = abs(a[0] - k);     // let this be the sum    // of the subarray    // to be searched initially    int sum = presum;     // iterate for all the array elements    for (int i = 1; i < n; i++) {         // calculate the prefix sum        presum += a[i];         // find the closest subarray        // sum to by using lower_bound        auto it = s.lower_bound(presum - k);         // if it is the first element        // in the set        if (it == s.begin()) {             // get the prefix sum till start            // of the subarray            int diff = *it;             // if the subarray sum is closest to K            // than the previous one            if (abs((presum - diff) - k) < mini) {                 // update the minimal difference                mini = abs((presum - diff) - k);                 // update the sum                sum = presum - diff;            }                           if(abs(presum - k) < mini){              // update the minimal difference                  mini = abs((presum - diff) - k);                   // update the sum                  sum = presum - diff;              }        }         // if the difference is        // present in between        else if (it != s.end()) {             // get the prefix sum till start            // of the subarray            int diff = *it;             // if the subarray sum is closest to K            // than the previous one            if (abs((presum - diff) - k) < mini) {                 // update the minimal difference                mini = abs((presum - diff) - k);                 // update the sum                sum = presum - diff;            }             // also check for the one before that            // since the sum can be greater than            // or less than K also            it--;             // get the prefix sum till start            // of the subarray            diff = *it;             // if the subarray sum is closest to K            // than the previous one            if (abs((presum - diff) - k) < mini) {                 // update the minimal difference                mini = abs((presum - diff) - k);                 // update the sum                sum = presum - diff;            }        }         // if there exists no such prefix sum        // then the current prefix sum is        // checked and updated        else {             // if the subarray sum is closest to K            // than the previous one            if (abs(presum - k) < mini) {                 // update the minimal difference                mini = abs(presum - k);                 // update the sum                sum = presum;            }        }         // insert the current prefix sum        s.insert(presum);    }     return sum;} // Driver Codeint main(){    int a[] = { -5, 12, -3, 4, -15, 6, 1 };    int n = sizeof(a) / sizeof(a[0]);    int k = 2;     cout << closestSubarraySumToK(a, n, k);    return 0;}
// Java program to find the// sum of subarray whose sum is// closest to Kimport java.util.*; class GFG{   // Function to find the sum of subarray  // whose sum is closest to K  static int closestSubarraySumToK(int a[], int n, int k)  {     // Declare a set    TreeSet<Integer> s = new TreeSet<>();     // initially consider the    // first subarray as the first    // element in the array    int presum = a[0];     // insert    s.add(a[0]);     // Initially let this difference    // be the minimum    int mini = Math.abs(a[0] - k);     // let this be the sum    // of the subarray    // to be searched initially    int sum = presum;     // iterate for all the array elements    for (int i = 1; i < n; i++) {       // calculate the prefix sum      presum += a[i];       // find the closest subarray      // sum to by using lower_bound      Integer it = s.lower(presum - k);       // if it is the first element      // in the set      if (it == s.first()) {         // get the prefix sum till start        // of the subarray        int diff = it;         // if the subarray sum is closest to K        // than the previous one        if (Math.abs((presum - diff) - k) < mini) {           // update the minimal difference          mini = Math.abs((presum - diff) - k);           // update the sum          sum = presum - diff;        }      }       // if the difference is      // present in between      else if (it == s.last()) {         // get the prefix sum till start        // of the subarray        int diff = it;         // if the subarray sum is closest to K        // than the previous one        if (Math.abs((presum - diff) - k) < mini) {           // update the minimal difference          mini = Math.abs((presum - diff) - k);           // update the sum          sum = presum - diff;        }         // also check for the one before that        // since the sum can be greater than        // or less than K also        it--;         // get the prefix sum till start        // of the subarray        diff = it;         // if the subarray sum is closest to K        // than the previous one        if (Math.abs((presum - diff) - k) < mini) {           // update the minimal difference          mini = Math.abs((presum - diff) - k);           // update the sum          sum = presum - diff;        }      }       // if there exists no such prefix sum      // then the current prefix sum is      // checked and updated      else {         // if the subarray sum is closest to K        // than the previous one        if (Math.abs(presum - k) < mini) {           // update the minimal difference          mini = Math.abs(presum - k);           // update the sum          sum = presum+1;        }      }       // insert the current prefix sum      s.add(presum);    }     return sum;  }   // Driver Code  public static void main(String[] args)  {    int a[] = { -5, 12, -3, 4, -15, 6, 1 };    int n = a.length;    int k = 2;     System.out.print(closestSubarraySumToK(a, n, k));  }} // This code contributed by Rajput-Ji
# Python3 program to find the# sum of subarray whose sum is# closest to Kimport bisect # Function to find the sum of subarray# whose sum is closest to Kdef closestSubarraySumToK(a , n , k):         # Declare a set    s = []     # initially consider the    # first subarray as the first    # element in the array    presum = a[0]     # insert    s.append(a[0])     # Initially let this difference    # be the minimum    mini = abs(a[0] - k)     # let this be the sum    # of the subarray    # to be searched initially    sum = presum     # iterate for all the array elements    for i in range(1, n):         # calculate the prefix sum        presum += a[i]         # find the closest subarray        # sum to by using lower_bound        it = bisect.bisect_left(s,presum - k)                 if(it == -1):            continue                         #if it is the first element        # in the set        if (it == 0):             #get the prefix sum till start            #of the subarray            diff = s[it]             # if the subarray sum is closest to K            # than the previous one            if (abs((presum - diff) - k) < mini):                 # update the minimal difference                mini = abs((presum - diff) - k)                 # update the sum                sum = presum - diff                         if (abs(presum - k) < mini):                #update the minimal difference                mini = abs((presum - diff) - k)                                 #update the sum                sum = presum - diff                                       # if the difference is        # present in between        elif (it != len(s)):                         # get the prefix sum till start            # of the subarray            diff = s[it]             # if the subarray sum is closest to K            # than the previous one            if (abs((presum - diff) - k) < mini):                 # update the minimal difference                mini = abs((presum - diff) - k)                 # update the sum                sum = presum - diff                              # also check for the one before that            # since the sum can be greater than            # or less than K also            it -= 1             # get the prefix sum till start            # of the subarray            diff = s[it]             # if the subarray sum is closest to K            # than the previous one            if (abs((presum - diff) - k) < mini):                 # update the minimal difference                mini = abs((presum - diff) - k)                 # update the sum                sum = presum - diff;          # if there exists no such prefix sum        # then the current prefix sum is        # checked and updated        else :             # if the subarray sum is closest to K            # than the previous one            if (abs(presum - k) < mini):                 # update the minimal difference                mini = abs(presum - k)                 # update the sum                sum = presum + 1;         # insert the current prefix sum        bisect.insort(s, presum)     return sum           # Driver Codea = [ -5, 12, -3, 4, -15, 6, 1 ]n = len(a)k = 2 print(closestSubarraySumToK(a, n, k)) #This code is contributed by phasing17
// C# program to find the// sum of subarray whose sum is// closest to Kusing System;using System.Linq;using System.Collections.Generic; public class GFG {   // Function to find the sum of subarray  // whose sum is closest to K  static int closestSubarraySumToK(int []a, int n, int k) {     // Declare a set    SortedSet<int> s = new SortedSet<int>();     // initially consider the    // first subarray as the first    // element in the array    int presum = a[0];     // insert    s.Add(a[0]);     // Initially let this difference    // be the minimum    int mini = Math.Abs(a[0] - k);     // let this be the sum    // of the subarray    // to be searched initially    int sum = presum;     // iterate for all the array elements    for (int i = 1; i < n; i++) {       // calculate the prefix sum      presum += a[i];       // find the closest subarray      // sum to by using lower_bound      int it = lower_bound(s,presum - k);       // if it is the first element      // in the set      if (it == s.First()) {         // get the prefix sum till start        // of the subarray        int diff = it;         // if the subarray sum is closest to K        // than the previous one        if (Math.Abs((presum - diff) - k) < mini) {           // update the minimal difference          mini = Math.Abs((presum - diff) - k);           // update the sum          sum = presum - diff;        }      }       // if the difference is      // present in between      else if (it == s.Last()) {         // get the prefix sum till start        // of the subarray        int diff = it;         // if the subarray sum is closest to K        // than the previous one        if (Math.Abs((presum - diff) - k) < mini) {           // update the minimal difference          mini = Math.Abs((presum - diff) - k);           // update the sum          sum = presum - diff;        }         // also check for the one before that        // since the sum can be greater than        // or less than K also        it--;         // get the prefix sum till start        // of the subarray        diff = it;         // if the subarray sum is closest to K        // than the previous one        if (Math.Abs((presum - diff) - k) < mini) {           // update the minimal difference          mini = Math.Abs((presum - diff) - k);           // update the sum          sum = presum - diff;        }      }       // if there exists no such prefix sum      // then the current prefix sum is      // checked and updated      else {         // if the subarray sum is closest to K        // than the previous one        if (Math.Abs(presum - k) < mini) {           // update the minimal difference          mini = Math.Abs(presum - k);           // update the sum          sum = presum + 1;        }      }       // insert the current prefix sum      s.Add(presum);    }     return sum-1;  }  public static int lower_bound(SortedSet<int> s, int val)  {    List<int> temp = new List<int>();    temp.AddRange(s);    temp.Sort();    temp.Reverse();     if (temp.IndexOf(val) + 1 == temp.Count)      return -1;    return temp[temp.IndexOf(val) + 1];  }   // Driver Code  public static void Main(String[] args) {    int []a = { -5, 12, -3, 4, -15, 6, 1 };    int n = a.Length;    int k = 2;     Console.Write(closestSubarraySumToK(a, n, k));  }} // This code is contributed by Rajput-Ji
<script>// javascript program to find the// sum of subarray whose sum is// closest to K     // Function to find the sum of subarray    // whose sum is closest to K    function closestSubarraySumToK(a , n , k) {         // Declare a set        var s = [];         // initially consider the        // first subarray as the first        // element in the array        var presum = a[0];         // insert        s.push(a[0]);         // Initially let this difference        // be the minimum        var mini = Math.abs(a[0] - k);         // let this be the sum        // of the subarray        // to be searched initially        var sum = presum;         // iterate for all the array elements        for (var i = 1; i < n; i++) {            s.sort();                         // calculate the prefix sum            presum += a[i];             // find the closest subarray            // sum to by using lower_bound            var it = lower_bound(s,presum - k);            if(it == -1)                continue;                             // if it is the first element            // in the set            if (it == s[0]) {                 // get the prefix sum till start                // of the subarray                var diff = it;                 // if the subarray sum is closest to K                // than the previous one                if (Math.abs((presum - diff) - k) < mini) {                     // update the minimal difference                    mini = Math.abs((presum - diff) - k);                     // update the sum                    sum = presum - diff;                }            }             // if the difference is            // present in between            else if (it == s[s.length-1]) {                 // get the prefix sum till start                // of the subarray                var diff = it;                 // if the subarray sum is closest to K                // than the previous one                if (Math.abs((presum - diff) - k) < mini) {                     // update the minimal difference                    mini = Math.abs((presum - diff) - k);                     // update the sum                    sum = presum - diff;                }                 // also check for the one before that                // since the sum can be greater than                // or less than K also                it--;                 // get the prefix sum till start                // of the subarray                diff = it;                 // if the subarray sum is closest to K                // than the previous one                if (Math.abs((presum - diff) - k) < mini) {                     // update the minimal difference                    mini = Math.abs((presum - diff) - k);                     // update the sum                    sum = presum - diff;                }            }             // if there exists no such prefix sum            // then the current prefix sum is            // checked and updated            else {                 // if the subarray sum is closest to K                // than the previous one                if (Math.abs(presum - k) < mini) {                     // update the minimal difference                    mini = Math.abs(presum - k);                     // update the sum                    sum = presum + 1;                }            }             // insert the current prefix sum            s.push(presum);        }         return sum;    }    function lower_bound(s, val) {        let temp = [...s];        temp.sort((a, b) => a - b);        return temp[temp.indexOf(val) + 1];    }         // Driver Code        var a = [ -5, 12, -3, 4, -15, 6, 1 ];        var n = a.length;        var k = 2;         document.write(closestSubarraySumToK(a, n, k)); // This code is contributed by Rajput-Ji</script>
1
Time Complexity: O(N log N), where N represents the size of the given array.Auxiliary Space: O(N), where N represents the size of the given array.
anikaseth98
Rajput-Ji
songsgaana08
phasing17
samim2000
Binary Search
cpp-set
subarray
subarray-sum
Arrays
Binary Search Tree
Arrays
Binary Search Tree
Binary Search
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.