LeetCode: 560. Subarray Sum Equals K
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] | 3 | 4 | 7 | 2 | -3 | 1 | 4 | 3 | |
sum[i] (到第i位為止的累加和) | 0 | 3 | 7 | 14 | 16 | 13 | 14 | 18 | 21 |
hashmap key (到第i位為止出現過的累加和的值) | 0 | 3 | 7 | 14 | 16 | 13 | 14 | 18 | 21 |
hashmap value (到第i位為止出現過的累加和的值的對應次數) | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 1 |
count = hashmap(sum[i] - k) + 1 | 0 | - | 1 | 2 | - | - | 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;
}
相關文章
- [LeetCode] 560. Subarray Sum Equals KLeetCode
- LeetCode-Maximum Size Subarray Sum Equals kLeetCode
- [LeetCode] Minimum Size Subarray SumLeetCode
- LeetCode-Minimum Size Subarray SumLeetCode
- [LeetCode] 523. Continuous Subarray SumLeetCode
- [LeetCode] 2841. Maximum Sum of Almost Unique SubarrayLeetCode
- Leetcode 209. Minimum Size Subarray SumLeetCode
- LeetCode 209. Minimum Size Subarray Sum ?LeetCode
- LintCode-Subarray Sum
- LintCode-Subarray Sum Closest
- LeetCode 974 Subarray Sums Divisible by K All In OneLeetCode
- [LintCode/LeetCode] Check Sum of K PrimesLeetCode
- LeetCode-Max Sum of Rectangle No Larger Than KLeetCode
- Leetcode Maximum SubarrayLeetCode
- Leetcode Maximum Product SubarrayLeetCode
- Leetcode-Maximum SubarrayLeetCode
- Maximum Subarray leetcode javaLeetCodeJava
- LeetCode 560. 和為K的子陣列(字首和+雜湊+問題轉化)LeetCode陣列
- Leetcode-Maximum Product SubarrayLeetCode
- [leetCode][001] Maximum Product SubarrayLeetCode
- Leetcode Path SumLeetCode
- leetcode Sum系列LeetCode
- Leetcode Two SumLeetCode
- leetcode15&16_3Sum&4SumLeetCode
- LeetCode | 152. Maximum Product SubarrayLeetCode
- LintCode-K Sum
- Leetcode 1 two sumLeetCode
- Leetcode 3SumLeetCode
- Leetcode 4SumLeetCode
- Leetcode Path Sum IILeetCode
- Leetcode-Path SumLeetCode
- Leetcode-Two SumLeetCode
- Leetcode-3SumLeetCode
- Path Sum leetcode javaLeetCodeJava
- Two Sum leetcode javaLeetCodeJava
- 3 Sum leetcode javaLeetCodeJava
- 4 Sum leetcode javaLeetCodeJava
- LeetCode | 1 Two SumLeetCode