前缀和+哈希表 连续的子数组和 leetcode53题
Posted milaiko
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前缀和+哈希表 连续的子数组和 leetcode53题相关的知识,希望对你有一定的参考价值。
连续的子数组和
看到该题,一帮来讲能够想到使用前缀和来写。
前缀和
比如
nums = [23, 2, 4, 6,7] ,k =6
这时候会想到去用一数组 sums[n]
sum[0] = nums[0];
for(int i=1;i<n;i++){
sum[i] = sum[i-1]+nums[i];
}
得到前缀和后,又得设置两个索引i
和j
, 因为这里求的是子数组,比如[2,4]
就需要 sum[3] - sum[0]
然后求余得到0去判断。
前缀和+ 哈希表
但是因为nums.length <= 10^5
, 而我们上面的做法的复杂度为o(n^2), 这很容易超时。要怎么做能减小时间复杂度呢?
s u m [ j ] − s u m [ i ] = n ∗ k ; t h e n ( s u m [ j ] − s u m [ i ] ) / k = n sum[j] - sum[i] = n*k;\\\\then \\space (sum[j]-sum[i])/k = n sum[j]−sum[i]=n∗k;then (sum[j]−sum[i])/k=n
然后在仔细想一下, s u m [ j ] / k − s u m [ j ] / k = n sum[j]/k - sum[j]/k = n sum[j]/k−sum[j]/k=n(这里的除法会留有浮点数)
那这样的话,只要在遍历sums的时候,当sums有两个数对k取到的余数相同,就可以实现上面的公式。
// 连续的子数组和
// 要求的是子数组总和为k的倍数
#include"head.h"
class Solution{
public:
bool checkSubarraySum(vector<int>& nums, int k){
int m = nums.size();
if(m < 2){
return false; // 连子数组的最小个数都凑不起
}
unordered_map<int, int> mp;
mp[0] = -1;
int remainder = 0; //余数
//通过余数累加的方式,去实现前缀和的思想
for(int i=0;i<m;i++){
remainder = (remainder + nums[i])%k;
if(mp.count(remainder)){
int preIndex = mp[remainder];
if(i - remainder >= 2){
return true;
}
}else {
mp[remainder] = i;
}
}
return false;
}
};
以上是关于前缀和+哈希表 连续的子数组和 leetcode53题的主要内容,如果未能解决你的问题,请参考以下文章