【leetcode】560. 和为 K 的子数组
题目:
560. 和为 K 的子数组 - 力扣(LeetCode) (leetcode-cn.com)
思路1:前缀和
计算数组的前缀和,presum[i]等于nums[0...i-1]所有数的和,presum[0] = 0;
则nums[j...i-1]的值等于presum[i]减去presum[j];
要保证i和j是不越界的
故我们可以遍历全部的子数组num[j...i],再通过前缀和计算子数组中的值的和有多少等于k的,从而计算得出和为k的子数组数量
代码如下:
class Solution { public int subarraySum(int[] nums, int k) { //构造前缀和数组 //preSum 记录 nums[0..i-1] 的累加和 int[] preSum = new int[nums.length+1]; preSum[0] = 0; for(int i=1;i<preSum.length;i++){ preSum[i] = preSum[i-1]+nums[i-1]; } int ans = 0; //穷举所有的子数组 nums[j..i-1]= presum[i] - presum[j] // 从上看j是要小于i的,小于等于i-1 // 在保证num[j...i-1]中的i-1和j不越界的情况下,也保证了presum中的i和j不越界,穷举出所有的可能的子数数组 for(int i=1;i<=nums.length;i++){ // j是可以等于i-1的 for(int j=0;j<i;j++){ if(preSum[i]-preSum[j]==k) ans++; } } return ans; } }
思路2: 前缀和+哈希表
优化的思路是:我直接记录下有几个 preSum[j]
和 preSum[i] - k
相等,直接更新结果,就避免了内层的 for 循环。我们可以用哈希表,在记录前缀和的同时记录该前缀和出现的次数。
代码:
class Solution { public int subarraySum(int[] nums, int k) { //构造前缀和数组 //preSum 记录 nums[0..i-1] 的累加和 //构建哈希表:表示当前出现的前缀和出现了几次 HashMap<Integer,Integer> mp = new HashMap<>(); mp.put(0,1); int ans = 0,prev = 0; //穷举所有的子数组 nums[j..i-1]= presum[i] - presum[j] // presum[i] - presum[j] == k,即是要找到j值。且j是小于i的 for(int i=0;i<nums.length;i++){ prev += nums[i]; if(mp.containsKey(prev-k)) ans += mp.get(prev-k); mp.put(prev,mp.getOrDefault(prev,0)+1); } return ans; } }