Search code examples
javaalgorithmdata-structures

Why is this sliding window?


https://leetcode.com/problems/subarray-sum-equals-k/solutions/3662440/easy-java-sliding-window-o-n/

I don't understand the strategy here. The answer below is listed in the category of 'sliding window'. I understand what that is, but how does this solution implement that? With sliding window, I'd expect sum to be re-initialized to zero at some point, but it's not here.

To me, at least part of the strategy is that map stores sums as keys, all with values of 1. If a sum-k key is present, increment result with key's value. Be that true or not, i don't understand the condition with which result is incremented.

Can someone please explain?

public int subarraySum(int[] nums, int k) {
    int sum = 0, result = 0;
    Map<Integer, Integer> preSum = new HashMap<>();
    preSum.put(0, 1);
    
    for (int i = 0; i < nums.length; i++) {
        sum += nums[i];
        if (preSum.containsKey(sum - k)) {
            result += preSum.get(sum - k);
        }
        preSum.put(sum, preSum.getOrDefault(sum, 0) + 1);
    }
    return result;
}

Solution

  • part of the strategy is that map stores sums as keys, all with values of 1.

    Yes, that would be true if the input numbers are all positive numbers. But realise that the input values may be negative. This scenario is not presented in the two examples that are given, so let me give you one:

    Input: nums = [1, -1, 1, -1, 1, -1], k = 0
    Output: 9
    

    The sub arrays that are counted, can be represented as follows:

    [1, -1]                  // 1 that has its last element at index 1
       [-1, 1]               // 1 that has its last element at index 2
    [1, -1, 1, -1]           // 2 that have their last elements at index 3
           [1, -1] 
       [-1, 1, -1, 1]        // 2 that have their last elements at index 4
              [-1, 1]
    [1, -1, 1, -1, 1, -1]    // 3 that have their last elements at index 5
           [1, -1, 1, -1]
                  [1, -1]
    

    As there are many overlapping sub arrays that sum up to 0, the map becomes useful: for each value of the running sum, it has an entry that gives the number of sub arrays so far that have that same sum.

    We can monitor the evolution of the map (and the sum and result) for this example:

    i sum sum - k get from map result put in map map
    before loop 0 -- -- 0 put(0, 1) { 0: 1 }
    0 1 1 -- 0 put(1, 1) { 0: 1, 1: 1 }
    1 0 0 get(0) → 1 1 put(0, 2) { 0: 2, 1: 1 }
    2 1 1 get(1) → 1 2 put(1, 2) { 0: 2, 1: 2 }
    3 0 0 get(0) → 2 4 put(0, 3) { 0: 3, 1: 2 }
    4 1 1 get(1) → 2 6 put(1, 3) { 0: 3, 1: 3 }
    5 0 0 get(0) → 3 9 put(0, 4) { 0: 4, 1: 3 }

    I wouldn't call this a sliding window algorithm though.