刷题日记和为 K 的子数组
Posted 傅耳耳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题日记和为 K 的子数组相关的知识,希望对你有一定的参考价值。
和为 K 的子数组
给定一个整数数组和一个整数 k ,请找到该数组中和为 k 的连续子数组的个数。
示例 1:
输入:nums = [1,1,1], k = 2
输出: 2
解释: 此题 [1,1] 与 [1,1] 为两种不同的情况
示例 2:
输入:nums = [1,2,3], k = 3
输出: 2
提示:
1 <= nums.length <= 2 * 10^4
-1000 <= nums[i] <= 1000
-10^7 <= k <= 10^7
【滑动窗口思维】
- 确定左右边界
- 查找窗口左右滑动的条件
适合求解相关 [连续子数组] 题目
【局限性】但在存在==负数==的数组中不能使用
窗口滑动的条件:
while窗口内元素超过或不满足条件时
滑动窗口;若存在负数,则不能确定是移动左边界 or 扩大右边界
思路:前缀和 + 哈希表
适用解题:循环数组的下标N时,需要用到前N-1项的计算结果(和/积)
如何保存?
- 题目明确要求不允许使用额外空间的,直接原地修改数组
- 不限制空间复杂度时,最好额外开辟空间计算,避免数据污染
- 计算时每次只需获取前一次的累计结果 ===> 使用数组存储,每次获取数组末尾元素
- 计算时每次需获取前几次或更多次的结果进行对比 ===> 使用哈希表存储,减小时间复杂度
算法步骤
前缀和差值 = 连续子数组的和
- 找连续子数组的和为K <==> 找
pre[j] - pre[i-1] == k
的下标对[i,j]
pre[j] - pre[i - 1] == k
等价于pre[j] - k == pre[i - 1]
- 即当前前缀和 - k 所得为前面某些元素的前缀和
-
哈希表
hashmap
==> 保存已经出现的前缀和 出现的次数,不仅仅是1例:
[-1,1,0], k = 0
-
当遍历到最后一个元素时
presum = 0
-
presum - k = 0
,前缀和为0的部分有[-1,1]
和[-1,1,0]
-
-
不断累加计算当前前缀和
presum
,并判断presum - k
是否在hashmap
中,若存在,结果 + 次数hashmap[presum-k]
,并保存当前前缀和presum
到hashmap
中
【边界问题】若nums[0] = k
,但当前 hashmap
为空,不会统计 ==> 初始化 hashmap
为 0:1
代码
class Solution
public:
int subarraySum(vector<int>& nums, int k)
map<int, int> hashmap;
int presum = 0;
int res = 0;
hashmap[0] = 1;
for(int i = 0;i < nums.size();i ++ )
presum += nums[i];
// 判断presum-k所得的前缀和是否存在
if(hashmap.find(presum - k) != hashmap.end())
res += hashmap[presum-k] ;
// 保存当前前缀和
hashmap[presum] ++ ;
return res;
;
时间复杂度:O(n)
空间复杂度:O(n)
以上是关于刷题日记和为 K 的子数组的主要内容,如果未能解决你的问题,请参考以下文章