560 和为K的连续子数组
优雅的暴力(累加和)
分析题目可以知道所求是在给定数组范围内求解区间(i,j)的子数组之和sum使得sum = k
- 通过两层循环依次求出所有累加和与K值比较
C++代码实现如下
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
// 累计和
/*
vector<int> sum(nums.size()+1, 0);
for(int i=1; i<sum.size(); ++i){
sum[i] += sum[i-1] + nums[i-1];
} // 累计和sum[i] 为 nums数组[0,i)区间的累计和
// [i,j)区间累计和即为sum[j] - sum[i]
*/
int res = 0;
for(int i=0; i<nums.size(); ++i){
int sum = 0;
for(int j=i; j< nums.size(); ++j){
sum += nums[j]; if(sum == k) res++;
}
}
return res;
}
};
时间复杂度:O(N^2)
空间复杂度:O(1)
由于时间复杂度为N^2故运行时间并不理想,但依然可以通过测试数据,因为系数K较低,如果是建立数组存储所有sum和再进行加减操作就是注释里得部分就无法通过了
思考优化
本质上是求(i,j) 的累加和与K比较判断是否相等
有什么办法可以通过一次循环得到所求呢
建立累加和数组sums,其中sums[i]表示[0,i]区间内的累加和
tips 这里的区间表示我觉得非常重要,因为开闭区间包含与不包含对数据的处理和思路的分析有很大的影响,
个人感觉算法很多时候细节非常重要
[i, j)区域内的累加和我们就可以用sums[j] - sums[i]得到
也就是说如果sums[j] - sums[i] = k 就是我们选择的一个方案
之前的方法是求出所有的累加和,但这其实进行了很多不必要的操作,我们从另外一个思路出发
每次进行循环的时候我们得到了一个[0,j]的累加和sum.我们记录这个sum
如果sum - k 的值存在我们的记录中,就意味着我们得到了一个解决方案
因此我们用hash表记录在循环过程中所有求得的sum
还记得之前我们所用到得是闭区间吧那如果是[0,i]为所求得子数组呢.
初始化得时候让表内多一个值为0个数为1 的初始键值就可以解决这个问题
c++代码如下
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
// 累计和
// 存储sum值
int res = 0, sum = 0;
unordered_map<int, int>mp;
mp[0] = 1;
for(auto num:nums){
sum += num;
if(mp[sum - k] > 0) res += mp[sum - k];
mp[sum]++;
}
return res;
}
};
时空复杂度均为O(N)
- C++的map对所有未存在的键值会自动赋值0;
- C++的map查找元素是用的红黑树,因此其查找时间复杂度并不是O(1)但可以在小数据时候视作O(1)
博客探讨了LeetCode中的第560题,即寻找和为K的连续子数组问题。文章提到了一种暴力方法,通过累加和来解决,虽然时间复杂度较高,但在数据量较小的情况下仍能通过测试。作者强调了区间表示对解题思路的重要性,并提供了C++代码实现,利用map的数据结构来优化查找效率。

2092

被折叠的 条评论
为什么被折叠?



