LeetCode 560. 和为K的子数组
https://leetcode-cn.com/problems/subarray-sum-equals-k/
这个题第一眼看以为是滑动窗口,直接用滑动窗口做被坑了,负数一出现就人没了。。。
后来直接暴力解,结果被 [0,0,0,0,0,0,0,0,0,0] 0 这个测试用例上了一堂课,乖乖把优化步骤去掉,才能勉强AC
class Solution { public int subarraySum(int[] nums, int k) { if (nums.length == 0) { return 0; } int res = 0; for(int i = 0; i < nums.length; i++){ int count = 0; for(int j = i; j >= 0; j--){ count += nums[j]; if(count == k){ res++; } } } return res; } }
暴力解O(n^2),效率很差,LeetCode给出的反馈如下
执行用时:387 ms
内存消耗:41 MB
后来看了评论区和提示,才明白tag中的哈希表是拿来干嘛用的,其实就是统计从0开始到i出现过的sum的次数,然后通过sum-k看看是否存在一个sum-k子数组,使得sum-k + k = sum。就像提示4里面所说的那样。
sum(i,j)=sum(0,j)-sum(0,i), where sum(i,j) represents the sum of all the elements from index i to j-1. Can we use this property to optimize it.
class Solution { public int subarraySum(int[] nums, int k) { int res = 0; HashMap<Integer, Integer> map = new HashMap<>(); int sum = 0; map.put(0,1); for(int i = 0; i < nums.length; i++){ sum += nums[i]; //其实k可以看成是一个连续的子数组构成的和,根据提示4,我们可以看从0到i的总和减去k这个子数组所代表的和的差是否出现在map中,如果出现就代表存在一个子数组,使得这个子数组加上k可以到达当前的数组,那么我们的结果就要加上这个子数组出现的次数。 if(map.containsKey(sum - k)){ res += map.get(sum-k); } map.put(sum,map.getOrDefault(sum,0)+1); } return res; } }