2

Background

You are given an array that includes positive and negative numbers. You are to find a subarray within the array that equals some value X. The input is the array and the X value. The output is the starting and ending index of the subarray.

Example

Array = [2,6,0,9,7,3,1,4,1,10] 
X = 15
Output = [1,3]

Following is the Code I found on geeks4geeks

  public static void subArraySum(int[] arr, int n, int sum) { 
        //cur_sum to keep track of cummulative sum till that point 
        int cur_sum = 0; 
        int start = 0; 
        int end = -1; 
        HashMap<Integer, Integer> hashMap = new HashMap<>(); 

        for (int i = 0; i < n; i++) { 
            cur_sum = cur_sum + arr[i]; 
            //check whether cur_sum - sum = 0, if 0 it means 
            //the sub array is starting from index 0- so stop 
            if (cur_sum - sum == 0) { 
                start = 0; 
                end = i; 
                break; 
            } 
            //if hashMap already has the value, means we already  
            // have subarray with the sum - so stop 
            if (hashMap.containsKey(cur_sum - sum)) { 
                start = hashMap.get(cur_sum - sum) + 1; 
                end = i; 
                break; 
            } 
            //if value is not present then add to hashmap 
            hashMap.put(cur_sum, i); 

        } 
        // if end is -1 : means we have reached end without the sum 
        if (end == -1) { 
            System.out.println("No subarray with given sum exists"); 
        } else { 
            System.out.println("Sum found between indexes " 
                            + start + " to " + end); 

QUESTION Overall I am able to understand why this solution works. The first block with the condition cur_sum - sum == 0 makes total sense to me.

However I am extremely confused about why the hashMap.containsKey(cur_sum - sum) check is working. I know that it works every time but I want to understand the mathematical significance behind it. I read in a interview blog that this uses the common diff technique but i am not sure how this applies to this.

I am not trying to memorize this solution as I prepare for interview but trying to build a solid understanding of why it is working.

I have spent hours coming up with examples and traced through them by hand and the solution works but I am not able to grasp why this technique works and i refuse to memorize it blindly.

For instance if we are talking about a array with positive numbers only then i know the "SLIDING WINDOW" technique can be used and that i am able to completely comprehend. As you expand the window the sum gets larger and as you close the window the sum gets smaller. This is not the case for the problem above and so would appreciate some help.

Dinero
  • 1,070
  • 2
  • 19
  • 44

1 Answers1

2

sum - is the number we want to achieve

cur_sum - is the sum of all the elements in the array so far

say that cur_sum - sum = x

Each step we update cur_sum at the beginning and if the condition that confuses you evaluates to false we update the hashmap and continue.

So far so good.

Now, why are we looking to see if x is already in the hashmap?

The answer to that is that if there was a previous index i which all the elements till that index (inclusive) had the sum of x, this means that from index i+1 till the current index, we have a subarray which sums to: cur_sum - x

And since we already know that cur_sum - sum = x that means that the subarray that starts at i+1 and ends at the current index sums exactly to sum.

Let's take the example you posted:

Array = [2,6,0,9,7,3,1,4,1,10] 
X = 15
Output = [1,3]

Let's iterate the array:
index 0: sum 2 => updating the map with (0:2)
index 1: sum 2+6=8 => updating the map with (1:8)
index 2: sum 2+6+0=8 => updating the map with (2:8)
index 3: sum 2+6+0+9=17 =>

but now we can see that the map already contains 17-15=2 (0:2) hence we know that the sum of the subarray that starts at index 1 (index 1 comes after zero from (0:2)) and ends at the current index: 3 - this subarray sums to 15.

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • 1
    I completely get the part where you iterate through the elements until you hit the case where cur_sum - sum = value that already exists. What I don't get is why does this work? Why is that when we find two equal values that the sum of the elements between them and including equal to the sum we are looking for? Is this some mathematical property? – Dinero May 26 '19 at 04:36
  • 2
    @Dinero please go over the part that explains this `cur_sum - sum = x` again. Then look at the example again, it is indeed a mathematical property which might be a little bit confusing, but once you'll get it - it will look much simpler! – Nir Alfasi May 27 '19 at 04:13
  • 1
    yes it makes sense i think i was overthinking. So from what i understand is when we get to index 3 in the above situation and we do 17 - 15 = 2. We know that we saw 2 before and since then we added value of 15 to get to 17, hence we know that i + 1 to the current end index is our subarray. – Dinero May 27 '19 at 16:50
  • @Dinero you got it bud! – Nir Alfasi May 27 '19 at 17:55