Find subarray with given sum with negatives allowed in constant space

Given an unsorted array of integers, find a subarray which adds to a given number. If there are more than one subarrays with the sum as the given number, print any of them.

Examples:

Input: arr[] = {1, 4, 20, 3, 10, 5}, sum = 33
Output: Sum found between indexes 2 and 4

Input: arr[] = {10, 2, -2, -20, 10}, sum = -10
Output: Sum found between indexes 0 to 3

Input: arr[] = {-10, 0, 2, -2, -20, 10}, sum = 20
Output: No subarray with given sum exists.

We had already discussed an approach to find subarray with a given sum in an array containing both positive and negative elements using Hashing



In this article, an approach without using any extra space is discussed.

The idea is to modify the array to contain only positive elements:

We may notice that after doing the above modification, the sum of every subarray will also increase by:

(number of elements in the subarray) * (absolute value of min element)

After, doing the above modification in the input array, the task reduces to find if there is any subarray in the given array of only positive numbers with the new target sum. This can be done using the sliding window technique in O(N) time and constant space.

Every time while adding elements to the window, increment the target sum by the absolute value of the minimum element and similarily while removing elements from the current window, decrement the target sum by the absolute value of the minimum element so that for every subarray of length say K, the updated target sum will be:

targetSum = sum + K*abs(minimum element)

Below is the approach for the same:

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to check if subarray with sum
// exists when negative elements are also present
#include <bits/stdc++.h>
using namespace std;
  
// Function to check if subarray with sum
// exists when negative elements are also present
void subArraySum(int arr[], int n, int sum)
{
    int minEle = INT_MAX;
  
    // Find minimum element in the array
    for (int i = 0; i < n; i++)
        minEle = min(arr[i], minEle);
  
    // Initialize curr_sum as value of first element
    // and starting point as 0
    int curr_sum = arr[0] + abs(minEle), start = 0, i;
  
    // Starting window length will be 1,
    // For generating new target sum,
    // add abs(minEle) to sum only 1 time
    int targetSum = sum;
  
    // Add elements one by one to curr_sum
    // and if the curr_sum exceeds the
    // updated sum, then remove starting element
    for (i = 1; i <= n; i++) {
  
        // If curr_sum exceeds the sum,
        // then remove the starting elements
        while (curr_sum - (i - start) * abs(minEle) > targetSum && start <= i - 1) {
            curr_sum = curr_sum - arr[start] - abs(minEle);
            start++;
        }
  
        // If curr_sum becomes equal to sum, then return true
        if (curr_sum - (i - start) * abs(minEle) == targetSum) {
            cout << "Sum found between indexes " << start << " and " << i - 1;
            return;
        }
  
        // Add this element to curr_sum
        if (i < n) {
            curr_sum = curr_sum + arr[i] + abs(minEle);
        }
    }
  
    // If we reach here, then no subarray
    cout << "No subarray found";
}
  
// Driver Code
int main()
{
    int arr[] = { 10, -12, 2, -2, -20, 10 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    int sum = -10;
  
    subArraySum(arr, n, sum);
  
    return 0;
}
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to check if subarray with sum 
// exists when negative elements are also present 
class GFG 
{
      
    // Function to check if subarray with sum 
    // exists when negative elements are also present 
    static void subArraySum(int arr[], int n, int sum) 
    
        int minEle = Integer.MAX_VALUE; 
      
        // Find minimum element in the array 
        for (int i = 0; i < n; i++) 
            minEle = Math.min(arr[i], minEle); 
      
        // Initialize curr_sum as value of 
        // first element and starting point as 0 
        int curr_sum = arr[0] + Math.abs(minEle);
        int start = 0, i; 
      
        // Starting window length will be 1, 
        // For generating new target sum, 
        // add abs(minEle) to sum only 1 time 
        int targetSum = sum; 
      
        // Add elements one by one to curr_sum 
        // and if the curr_sum exceeds the 
        // updated sum, then remove starting element 
        for (i = 1; i <= n; i++) 
        
      
            // If curr_sum exceeds the sum, 
            // then remove the starting elements 
            while (curr_sum - (i - start) * 
                   Math.abs(minEle) > targetSum && 
                                      start <= i - 1)
            
                curr_sum = curr_sum - arr[start] - 
                           Math.abs(minEle); 
                start++; 
            
      
            // If curr_sum becomes equal to sum,
            // then return true 
            if (curr_sum - (i - start) * 
                Math.abs(minEle) == targetSum) 
            
                System.out.println("Sum found between indexes " +
                                      start + " and " + (i - 1)); 
                return
            
      
            // Add this element to curr_sum 
            if (i < n)
            
                curr_sum = curr_sum + arr[i] + 
                             Math.abs(minEle); 
            
        
      
        // If we reach here, then no subarray 
        System.out.println("No subarray found"); 
    
      
    // Driver Code 
    public static void main (String[] args) 
    
        int arr[] = { 10, -12, 2, -2, -20, 10 }; 
        int n = arr.length; 
      
        int sum = -10
      
        subArraySum(arr, n, sum); 
    }
}
  
// This code is contributed by AnkitRai01
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to check if subarray with summ
# exists when negative elements are also present
  
# Function to check if subarray with summ
# exists when negative elements are also present
def subArraySum(arr, n, summ):
    minEle = 10**9
  
    # Find minimum element in the array
    for i in range(n):
        minEle = min(arr[i], minEle)
  
    # Initialize curr_summ as value of 
    # first element and starting poas 0
    curr_summ = arr[0] + abs(minEle)
    start = 0
  
    # Starting window length will be 1,
    # For generating new target summ,
    # add abs(minEle) to summ only 1 time
    targetSum = summ
  
    # Add elements one by one to curr_summ
    # and if the curr_summ exceeds the
    # updated summ, then remove starting element
    for i in range(1, n + 1):
  
        # If curr_summ exceeds the summ,
        # then remove the starting elements
        while (curr_summ - (i - start) * abs(minEle) > 
                       targetSum and start <= i - 1):
            curr_summ = curr_summ - arr[start] - abs(minEle)
            start += 1
  
        # If curr_summ becomes equal to summ,
        # then return true
        if (curr_summ - (i - start) * 
            abs(minEle) == targetSum):
            print("Sum found between indexes"
                          start, "and", i - 1)
            return
  
        # Add this element to curr_summ
        if (i < n):
            curr_summ = curr_summ + arr[i] + abs(minEle)
  
    # If we reach here, then no subarray
    print("No subarray found")
  
# Driver Code
arr = [10, -12, 2, -2, -20, 10]
n = len(arr)
  
summ = -10
  
subArraySum(arr, n, summ)
  
# This code is contributed by Mohit Kumar
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to check if subarray 
// with sum exists when negative 
// elements are also present 
using System;
  
class GFG
{
      
    // Function to check if subarray 
    // with sum exists when negative
    // elements are also present 
    static void subArraySum(int []arr, 
                            int n, int sum) 
    
        int minEle = int.MaxValue; 
        int i;
          
        // Find minimum element in the array 
        for (i = 0; i < n; i++) 
            minEle = Math.Min(arr[i], minEle); 
      
        // Initialize curr_sum as value of 
        // first element and starting point as 0 
        int curr_sum = arr[0] + Math.Abs(minEle);
        int start = 0; 
      
        // Starting window length will be 1, 
        // For generating new target sum, 
        // add abs(minEle) to sum only 1 time 
        int targetSum = sum; 
      
        // Add elements one by one to curr_sum 
        // and if the curr_sum exceeds the 
        // updated sum, then remove starting element 
        for (i = 1; i <= n; i++) 
        
      
            // If curr_sum exceeds the sum, 
            // then remove the starting elements 
            while (curr_sum - (i - start) * 
                   Math.Abs(minEle) > targetSum && 
                                      start <= i - 1)
            
                curr_sum = curr_sum - arr[start] - 
                           Math.Abs(minEle); 
                start++; 
            
      
            // If curr_sum becomes equal to sum,
            // then return true 
            if (curr_sum - (i - start) * 
                Math.Abs(minEle) == targetSum) 
            
                Console.Write("Sum found between indexes " +
                                 start + " and " + (i - 1)); 
                return
            
      
            // Add this element to curr_sum 
            if (i < n)
            
                curr_sum = curr_sum + arr[i] + 
                             Math.Abs(minEle); 
            
        
      
        // If we reach here, then no subarray 
        Console.Write("No subarray found"); 
    
      
    // Driver Code 
    static public void Main ()
    {
        int []arr = { 10, -12, 2, -2, -20, 10 }; 
        int n = arr.Length; 
      
        int sum = -10; 
      
        subArraySum(arr, n, sum); 
    }
}
  
// This code is contributed by ajit
chevron_right

Output:
Sum found between indexes 1 and 2


This article is contributed by Alexandru Cosmin Vlajoaga. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.





Article Tags :
Practice Tags :