题目一描述
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
说明
数组的长度为 [1, 20,000]。
数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。
思路
一开始,我并没有考虑到前缀和解法,我是直接暴力走的,暴力的思想其实挺简单的,就是固定左边界,右边界不断移动,直到和等于需要的值.
暴力代码
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int num;
num=0;
for(int i=0;i<nums.size();i++)
{
int sum;
sum=0;
for(int j=i;j<nums.size();j++)
{
sum+=nums[j];//需注意先加后判断.
if(sum==k)
{
num++;
}
}
}
return num;
}
};
结果可想而知,就是直接超时了.
毕竟时间复杂度为O(N^2)
当你选择前缀和去解决这个题目的时候,只有当你写的时候,才会发现其实前缀和的解法的时间复杂度也是O(N^2)
前缀和代码
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
vector<int> a(nums.size()+1);
a[0]=0;
int num;
num=0;
for(int i=0;i<nums.size();i++)
{
a[i+1]=nums[i]+a[i];
}
for(int i=0;i<nums.size();i++)
{
for(int j=i;j<nums.size();j++)
{
if(a[j+1]-a[i]==k)
{
num++;
}
}
}
return num;
}
};
那么你就需要去进行优化,这个优化也是根据别人题解学习的!!
方法是前缀和+哈希表优化
分析:
你会发现前缀和与暴力的解法,的时间复杂度都是一样,因为它存在一个嵌套循环,这两种方法都逃不过这个循环,那么我们应该如何避免这个事情呢?
我准备写题解,突然发现感觉和官方没有区别,为了节省时间就截图过来了!
官方题解
我自己对这个过程进行了一个简单模拟
抱歉,字可能丑了点!!
最终优化代码
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> mp;
int num,pre;
num=pre=0;
mp[0]=1;
for(int i=0;i<nums.size();i++)
{
pre+=nums[i];
if(mp.find(pre-k)!=mp.end())
{
num+=mp[pre-k];
}
mp[pre]++;
}
return num;
}
};
大家好,我是大一小菜鸡,又菜瘾还大!