LeetCode: 560. Subarray Sum Equals K

yexianyi發表於2020-11-18

Given an array of integers nums and an integer k, return the total number of continuous subarrays whose sum equals to k.

Example 1:

Input: nums = [1,1,1], k = 2
Output: 2

Example 2:

Input: nums = [1,2,3], k = 3
Output: 2

Constraints:

  • 1 <= nums.length <= 2 * 104
  • -1000 <= nums[i] <= 1000
  • -107 <= k <= 107

解法一:(暴力破解)

都會,程式碼略

解法二:(利用累加和)

這個解法利用的是,如果有a + k = b,那麼就必然有b - a = k的原理。a和b為別為陣列某兩位之前的數字累加和。換句話說,設sum[i]和sum[j] (j>i)分別是陣列第i位之前和第j位之前的數字累加和,那麼如果有sum[j] - sum[i] == k,那就說明從第i位到第j位上的數字加和等於k。

具體演算法:

宣告一個Hashmap,key為陣列累加和出現的值,value為該值在累加過程中出現的次數。

以[3,4,7,2,-3,1,4,3] k = 7為例,計算過程如下

nums[i] 3472-3143
sum[i]
(到第i位為止的累加和)
037141613141821
hashmap key
(到第i位為止出現過的累加和的值)
037141613141821
hashmap value 
(到第i位為止出現過的累加和的值的對應次數)
111111211

count = hashmap(sum[i] - k) + 1

0-12--3-5

在上述的計算過程中,第i位之前的累加值兩次出現14,在第一次出現14的時候因為14-k = 7,而7恰好在之前出現過一次,那麼count就在7出現的次數上加1,得到2。也就是說,在陣列遍歷到數字7的時候,前面已經有兩個數字(3,4)可以組成符合條件的子陣列了,那麼加上現在的7以後,就可以獨立組成另外一組子陣列,也就是[(3,4), (7)];而後當sum[i]第二次出現14的時候,14-k繼續等於7,那麼繼續在現有count基礎之上加上當前map中7出現的次數,也就是1,得到當前新的count數。也就是說當陣列遍歷到數字1的時候,在它之前已經有2個符合條件的子陣列出現過了,就是剛才的[(3,4), (7)],那麼加上現在這個當前值1,就組成了第三個符合條件的陣列,即[(3,4), (7),(7,2,-3,1)]。當遍歷的最後一個數字3的時候,sum[i]==21,但是21-k == 14,而14又在前面出現過2次,說明從陣列最後一位到最近一次出現累加和等於14的位置上,存在符合條件的子陣列(4,3),但是為什麼這裡要把count+2而不是像之前一樣+1呢?因為在最近一次(也就是第二次)出現累加和等於14之前,到第一次出現14之間的數字加和是0,因為0和任意陣列組合都符合題意要求,所以需要把這次加上。這也就是hashmap要記錄每個累加和出現次數的原因,因為只要累加和曾經出現過,那麼兩次累加和之間的數字加和就一定是0。(否則怎麼可能兩次累積和的數字一樣呢?)

總結一下上面的過程就是,如果在遍歷陣列的過程中發現sum[i] - k的值曾經出現過,那麼就意味著有一個新的符合條件的陣列出現,即從第i位到它之前的某一位,但具體是哪一位我們其實不用關心。如果非要關心的話,就是從當前第i位到上一次出現sum[i] - k的值的位置,比如當第二次遇到sum[i] == 14的時候,符合條件的子陣列就是從當前位第5位到上一次sum[i] == 14(即第一次sum[i]==14)的時候(i=2),它們之間的數字(7,2,-3,1)。

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

 

相關文章