560. Subarray Sum Equals K
问题:
给定数组(含有正数负数),求连续子集合和=k的子集合数。
Example 1: Input:nums = [1,1,1], k = 2 Output: 2 Note: The length of the array is in range [1, 20,000]. The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7].
解法:
方法1:
暴力求解:l 代表左边,r 代表右边
用 l 遍历数组,
内部嵌套 r=l 开始遍历数组,依次求和,==k的时候,res++
tip:注意:由于中间可能含有负数,不能在==k之后,立马continue。
代码参考:
1 class Solution { 2 public: 3 int subarraySum(vector<int>& nums, int k) { 4 int l=0, r=0; 5 int res=0; 6 int tmpsum=0; 7 for(l=0; l<nums.size(); l++){ 8 tmpsum=0; 9 for(r=l; r<nums.size(); r++){ 10 tmpsum+=nums[r]; 11 if(tmpsum==k){ 12 res++; 13 } 14 } 15 } 16 return res; 17 } 18 };
解法2:
前缀求和法:
每次求0~i的和,并把这个结果记录在hash表中,
因为数组中有正有负,因此同一个sum值,可能出现多次。hash的value则记录出现的次数,key记录该sum值
遍历右边,若存在满足要求的i~j的和( k=sum(i~j) ),那么
presum(j)=presum(i)+k
那么presum(i)=presum(j)-k
到当前的j为止,存在多少个presum(i),则有多少个可能满足要求。
res+=hash[presum(i)]
同时更新当前presum(j)到hash表中。
tip:注意:初始化,首先加入presum(0)有1个解到hash表中。
1 class Solution { 2 public: 3 int subarraySum(vector<int>& nums, int k) { 4 int l=0; 5 int res=0; 6 int presum=0; 7 unordered_map<int,int>sumhash; 8 //key:sum,value:same presum(0~i) happens cout 9 //sum(i~j)=sum(0~j)-sum(0~i)=presum(j)-presum(i) 10 //presum(i)=presum(j)-sum(i~j)=presum(j)-k 11 sumhash.insert({0,1}); 12 for(l=0; l<nums.size(); l++){ 13 presum+=nums[l]; 14 res+=sumhash[presum-k]; 15 sumhash[presum]++; 16 } 17 return res; 18 } 19 };