Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Given an input array find all subarrays with given sum K

Tags:

algorithm

Given an input array we can find a single sub-array which sums to K (given) in linear time, by keeping track of sum found so far and the start position. If the current sum becomes greater than the K we keep removing elements from start position until we get current sum <= K.

I found sample code from geeksforgeeks and updated it to return all such possible sets. But the assumption is that the input array consists of only +ve numbers.

bool subArraySum(int arr[], int n, int sum) {     int curr_sum = 0, start = 0, i;     bool found = false;      for (i = 0; i <= n; i++)     {         while (curr_sum > sum && start < i)         {             curr_sum = curr_sum - arr[start];             start++;         }          if (curr_sum == sum)         {             cout<<"Sum found in b/w indices: "<<start<<" & "<<(i-1)<<"\n";             curr_sum -= arr[start];             start++;             found = true;         }          // Add this element to curr_sum         if (i < n) {           curr_sum = curr_sum + arr[i];         }     }      return found; } 

My question is do we have such a solution for mixed set of numbers too (both positive and negative numbers)?

like image 235
user1071840 Avatar asked Feb 19 '13 01:02

user1071840


People also ask

How do you find the number of subarrays in an array?

The total number of subarrays in an array of size N is N * (N + 1) / 2. The count of subarrays with an odd product is equal to the total number of continuous odd elements present in the array. Therefore, count of subarrays with even product = (Total number of subarrays – Subarrays with the odd product).


2 Answers

There is no linear-time algorithm for the case of both positive and negative numbers.

Since you need all sub-arrays which sum to K, time complexity of any algorithm cannot be better than size of the resulting set of sub-arrays. And this size may be quadratic. For example, any sub-array of [K, -K, K, -K, K, -K, ...], starting and ending at positive 'K' has the required sum, and there are N2/8 such sub-arrays.

Still it is possible to get the result in O(N) expected time if O(N) additional space is available.

Compute prefix sum for each element of the array and insert the pair (prefix_sum, index) to a hash map, where prefix_sum is the key and index is the value associated with this key. Search prefix_sum - K in this hash map to get one or several array indexes where the resulting sub-arrays start:

hash_map[0] = [-1] prefix_sum = 0 for index in range(0 .. N-1):   prefix_sum += array[index]   start_list = hash_map[prefix_sum - K]   for each start_index in start_list:     print start_index+1, index   start_list2 = hash_map[prefix_sum]   start_list2.append(index) 
like image 185
Evgeny Kluev Avatar answered Oct 27 '22 03:10

Evgeny Kluev


Solution as given by @Evgeny Kluev coded in Java with a little explanation.

public static void main(String[] args) {     int[] INPUT = {5, 6, 1, -2, -4, 3, 1, 5};     printSubarrays(INPUT, 5); }  private static void printSubarrays(int[] input, int k) {     Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();     List<Integer> initial = new ArrayList<Integer>();     initial.add(-1);     map.put(0, initial);     int preSum = 0;      // Loop across all elements of the array     for(int i=0; i< input.length; i++) {         preSum += input[i];         // If point where sum = (preSum - k) is present, it means that between that          // point and this, the sum has to equal k         if(map.containsKey(preSum - k)) {   // Subarray found              List<Integer> startIndices = map.get(preSum - k);             for(int start : startIndices) {                 System.out.println("Start: "+ (start+1)+ "\tEnd: "+ i);             }         }          List<Integer> newStart = new ArrayList<Integer>();         if(map.containsKey(preSum)) {              newStart = map.get(preSum);         }         newStart.add(i);         map.put(preSum, newStart);     } } 
like image 44
Menezes Sousa Avatar answered Oct 27 '22 02:10

Menezes Sousa