leetcode [560. 和为K的子数组]
Posted BeicC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode [560. 和为K的子数组]相关的知识,希望对你有一定的参考价值。
(https://leetcode-cn.com/problems/subarray-sum-equals-k/)
1:暴力法:因为要求的子数组必须是连续的,所以答案肯定是某一大块减去某一小块的结果正好为k,这样就自然而然的想到前缀和,得到前缀和在暴力枚举就行了,算法复杂度O(n2),我的代码卡在了最后一组数据
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int n = nums.size();
vector<int> add(n+1,0);
for(int i = 1; i <= n; i++) {add[i] = add[i-1]+nums[i-1];}
int ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 0; j < i; j++){
if(add[i] - add[j] == k) ans++;
//if(add[i] - add[j] < k) break;
}
}
return ans;
}
};
2:前缀和加map优化:我们在利用上一个方法的add[i] - add[j] == k,移项可得到add[j] = add[i]-k ,我们发现暴力方法的时间都浪费在找add[j] 上了,所以我们可以利用一个map来记录add[i] 前的所有前缀和,如果在map中能找到add[i]-k ,我们就加上对应的个数
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int n = nums.size();
map<int,int> M;
M[0] = 1;
int ans = 0,cnt = 0;
for(int i = 0; i < n; i++){
cnt += nums[i];
int p = cnt-k;
if(M.find(p) != M.end()) ans += M[p];
M[cnt]++;
}
return ans;
}
};
这个值得说的是,这里的是一步一步求得前缀和,不像我的暴力法中一下子把所有前缀和都给求出来了,这样得好处是对于每个i对应得前缀和,此时map里存的是他前面的所有前缀和,这样才能保证其正确性
以上是关于leetcode [560. 和为K的子数组]的主要内容,如果未能解决你的问题,请参考以下文章