前缀和+哈希表——560. 和为 K 的子数组

文章目录

🪐1. 题目

题目链接:560. 和为 K 的子数组 - 力扣(LeetCode)

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 2 * 104
  • -1000 <= nums[i] <= 1000
  • -107 <= k <= 107

🌟2. 算法原理

这题要找的是连续的子数组,例如:

⭐解法一:暴力枚举

固定一个位置,找到一个符合条件的ret++,当然了,这里还不能停,继续往后变量,直到数组结尾处,这个时间复杂度为O(n2)。

⭐解法二:前缀和+哈希表

在暴力枚举的过程中,这里固定的位置和往后遍历,虽然两个指针方向是一样的,但是不能使用滑动窗口,因为这个数组里面有负数0,并不是单调递增或者单调递减的,这样就会导致漏掉一些情况。

我们固定一个位置,往前遍历它的所有子数组,也可以理解为固定一个i位置,以i为结尾的所有子数组。

当枚举到i位置的时候,想找和为k的子数组就可以转换为在[0,i-1]区间内,有多少个前缀和为dp[i] - k的子数组。

我们把前缀和数组处理出来之后,要找i位置之前有多少个和为dp[i]-k,不能又从头到尾遍历,这样的时间复杂度还不如暴力求解

因此我们可以用哈希表 ,来快速找到在i之前有多少个前缀和是等于dp[i]-k的。那么哈希表里面的映射关系是前缀和出现的次数

细节问题:

  • 前缀和加入哈希表的时机:不能一股脑将前缀和全部丢进哈希表,我们只需要计算在i位置之前,哈希表里面只保存[0,i-1]位置的前缀和。
  • 不用真正的创建一个前缀和数组,只需借助一个临时变量,记录这个位置之前的前缀和,计算完毕之后,再更新一下这个临时变量。
  • 当整个前缀和为k时,我们需要在哈希表中默认有一个前缀和为0的位置hash[0]=1,以防这个情况被忽略。

此算法的时间复杂度为O(n)

🌞3. 代码实现

cpp 复制代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k)
    {
        unordered_map<int,int> hash;
        hash[0] = 1;

        int dp = 0;
        int ret = 0;
        for(auto e:nums)
        {
            dp+=e; //当前位置的前缀和
            if(hash.count(dp-k))    //在这个位置之前,有多少个前缀和为dp-k的
                ret+=hash[dp-k];
            hash[dp]++; 
        }
        return ret;
    }
};
相关推荐
长安er1 小时前
LeetCode 83/237/82 链表删除问题-盒子模型
数据结构·算法·leetcode·链表·力扣
重生之后端学习1 小时前
56. 合并区间
java·数据结构·后端·算法·leetcode·职场和发展
小猪猪屁1 小时前
顺序表与链表:头插法与尾插法详解
c语言·数据结构·c++
历程里程碑2 小时前
C++ 5:模板初阶
c语言·开发语言·数据结构·c++·算法
leoufung2 小时前
LeetCode 74. Search a 2D Matrix
数据结构·算法·leetcode
liu****3 小时前
一.脚手架介绍以及部分工具使用
开发语言·数据结构·c++·手脚架开发
R-G-B4 小时前
哈希表(hashtable),哈希理论,数组实现哈希结构 (C语言),散列理论 (拉链发、链接发),散列实现哈希结构,c++ 实现哈希
c语言·哈希算法·散列表·哈希表·数组实现哈希结构·散列实现哈希结构·c++ 实现哈希
历程里程碑4 小时前
C++ 6 :string类:高效处理字符串的秘密
c语言·开发语言·数据结构·c++·笔记·算法·排序算法
xu_yule4 小时前
算法基础-(数据结构)
数据结构
玩转数据库管理工具FOR DBLENS4 小时前
DBLens:开启数据库管理新纪元——永久免费,智能高效的国产化开发利器
数据结构·数据库·测试工具·数据库开发