前缀和+哈希表:联手合击Leetcode 560.和为k的子数组

题目

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k的子数组的个数

子数组是数组中元素的连续非空序列。

示例 1:

复制代码
输入:nums = [1,1,1], k = 2
输出:2

示例 2:

复制代码
输入:nums = [1,2,3], k = 3
输出:2

思路

因为这道题刚开始确实被刺了博主一把,所以有感而发下面多啰嗦两句警示大家。

仔细观察题目可以发现,表面人畜无害的题目背地里却暗藏杀机,博主在看到题目的第一瞬间扫描到 子数组 和为k 看了两个示例 顿时大喜,直接上手以迅雷不及掩耳之势敲出滑动窗口解法,试图直接通过left与right两员大将拿下此题,不出意外的话果然出意外了,在再次看到数据范围后果断将两位大将收回。另寻他法。

这里解释一下,滑动窗口是在题目所给数据具有单调性时,通过准确的把握单调性来减少遍历或枚举的次数从而达到降低时间复杂度的目的,而本题数据有正有负,且为乱序排列,我们无法准确把握每组数据的单调性,所以无法使用滑动窗口来进行解题。

而结合求和,子数组,和样例等种种特点排除滑动窗口后,前缀和无疑时此时最适合的方式。

可是涉及到子序列的问题,即使直接求出前缀和数组,如果进行简单的遍历再去一个个计算,那么复杂度直逼O(n^2),加上构造前缀和数组,复杂度还不如直接暴力枚举。所以需要在前缀和基础上进行优化,题目让求有多少个子集,那可以抽象为第i个结点之前有多少个符合和为k的结点,然后一个节点一个节点去求,从而可以再抽象为,第i个位置之前,有多少个节点等于第i个节点的前缀和-k。及判断在[0,i-1]区间内有多少个前缀和等于sum[i]-k;

因为数据没有单调性,所以i之前可能出现多个子串符合条件,而每次查找会消耗掉多余的时间,所以直接创建一个哈希表,对应进行查找,每次先查找再插入当前节点

注意:[0,i-1]==sum[i]-k,判断是否存在可以分为以下情况:

1、从0加到 i在nums数组中的那位刚好等于k,那sum[i]-k就是0;此时需要到0,-1区间去找,所以直接将哈希表0位置初始化成1,当这种情况出现时直接加上。

2、从0到i中间j位置的和刚好为sum[i]-k,那么从j+1到i的值就是k,符合情况。

3、i位置为k,那[0,i-1]就是sum[i]-k;

代码实现

class Solution { public: int subarraySum(vector<int>& nums, int k) { unordered_map<int,int> hash; hash[0]=1; int sum=0,ret=0; for(auto &x:nums) { sum+=x; if(hash.count(sum-k)) ret+=hash[sum-k]; hash[sum]++; } return ret; } };

相关推荐
0 0 06 分钟前
CCF-CSP 38-4 月票发行【C++】考点:动态规划DP+矩阵快速幂
c++·算法·动态规划·矩阵快速幂
北漂Zachary8 分钟前
Mysql中使用sql语句生成雪花算法Id
sql·mysql·算法
OxyTheCrack8 分钟前
【C++】详细拆解std::mutex的底层原理
linux·开发语言·c++·笔记
aini_lovee34 分钟前
MATLAB圆锥滚子轴承滚子参数分析程序
人工智能·算法·matlab
_olone38 分钟前
牛客每日一题:显生之宙(Java)
java·开发语言·算法·牛客
嫂子开门我是_我哥1 小时前
心电域泛化研究从0入门系列 | 第二篇:心电信号预处理全攻略——扫清域泛化建模的第一道障碍
人工智能·算法·ecg
wefg11 小时前
【算法】算数基本定理、分解质因数
算法
j_xxx404_1 小时前
力扣困难算法精解:串联所有单词的子串与最小覆盖子串
java·开发语言·c++·算法·leetcode·哈希算法
挠头猴子1 小时前
一个数组去重,两个数组找不同或相同
数据结构·算法
big_rabbit05022 小时前
[算法][力扣167]Two Sum II
算法·leetcode·职场和发展