前缀和+哈希表:联手合击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; } };

相关推荐
sp_fyf_202424 分钟前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
rjszcb36 分钟前
一文说完c++全部基础知识,IO流(二)
c++
小字节,大梦想1 小时前
【C++】二叉搜索树
数据结构·c++
吾名招财1 小时前
yolov5-7.0模型DNN加载函数及参数详解(重要)
c++·人工智能·yolo·dnn
我是哈哈hh2 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
憧憬成为原神糕手2 小时前
c++_ 多态
开发语言·c++
郭二哈2 小时前
C++——模板进阶、继承
java·服务器·c++
Tisfy2 小时前
LeetCode 2187.完成旅途的最少时间:二分查找
算法·leetcode·二分查找·题解·二分
挥剑决浮云 -2 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
Mephisto.java2 小时前
【力扣 | SQL题 | 每日四题】力扣2082, 2084, 2072, 2112, 180
sql·算法·leetcode