1.题目介绍

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

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

示例 1:

输入:nums = [1,1,1], k = 2

输出:2

示例 2:

输入:nums = [1,2,3], k = 3

输出:2

提示:

1 <= nums.length <= 2 * 104

-1000 <= nums[i] <= 1000

-107 <= k <= 107

2.题解

请注意题目中要求的连续非空序列,要求1.连续 2.非空!!!

2.1 枚举(O(n^2))

思路

最简单的思路是利用双重循环确定数组的开头和结尾,在利用一重循环来进行遍历相加

int count = 0;
for (int start = 0; start <= nums.size(); start++)
{
for (int end = start; end <= nums.size(); end++)
{
int sum = 0;
for (int i = start; i <= end; i++)
sum += nums[i];
if (sum == k) count++;
}
}

但是这里的时间复杂度达到了O(n^3),必定会超过限制,所以我们进行了一些优化

还是双重循环遍历,确定数组的两个端点

但每次并非从前向后,而是从后向前挨个相加检查。

start确定遍历子数组的右端点,这里end为何不是从0开始,而是从start开始呢?

这样有一个什么好处呢,就是我们每次都有着[j,i]的和

只要再加上nums[j-1],就可以再得到[j-1,i]。

如果end从0开始,其实就和上面的三重循环遍历没有区别了

题解

注意这里找到 sum == k的时候,不可以直接break,因为举个例子[-1,1,0] k = 0; 这时候start指向0这个数,发现sum = k直接break,子数组[-1,1,0]也满足条件但是没有算上!!!

class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int count = 0;
for (int start = 0; start < nums.size(); start++) {
int sum = 0;
for (int end = start; end >= 0; end--) {
sum += nums[end];
if (sum == k) {
count++;
}
}
}
return count;
}
};

2.2 前缀和 + 哈希表优化

思路

关于前缀和是啥,请参考:前缀和

即 存在:preSum[i] = preSum[i-1] + nums[i]

前缀和 就是从 nums 数组中的第 0 位置开始,累加到第 i 位置的结果,我们常把这个结果保存到数组 preSum 中,记为 preSum[i]。

降二重循环为一重循环:

我们可以基于方法一利用数据结构进行进一步的优化,我们知道方法一的瓶颈在于对每个 i,我们需要枚举所有的 j 来判断是否符合条件,所以可以优化为一重循环吗?

我们既然选用一重循环,就面临一个问题,我们只能确定一个参数,这里我们肯定选择区间的右端点,这样的话我们怎么知道其与另一端点构成的子数组和呢?

这里我们利用前缀和的思路去做即可,即我们需要一个数组或者哈希表来保存之前求得的和,即[0,i-1]的和。

这里还有一个问题:子数组可能不是从下标0开始,也有可能是[j,i], 也就是 preSum[i] - preSum[j] = k;

那换个思路是不是我只要用哈希表存储了[0,i-1]每个0开始子数组{如[0,0],[0,1],[0,2]...}的前缀和和其出现次数,

并且加上一个用于表示[0,i]这个数组的键值对{0,1} [preSum[i] -preSum[0]表示的是[1,i],这里我必须加上这个键值对,preSum[i]-0表示的才是[0,i]的值]。

在得到preSum[i] = preSum[i-1] + nums[i]后,由preSum[i] - preSum[j] = k;演变为preSum[j] = preSum[i] - k; 寻找哈希表中值为preSum[i] - k的存在及其出现次数,若存在,将count加上出现次数;不存在,继续遍历即可。

但我们再仔细想想,已经使用了哈希表存储了前缀和及其出现次数,我们还需要用preSum数组来存储前缀和吗?明显是不需要的,我们只需要维护一个前缀和变量pre即可

这里不使用数组存储也是考虑到数组无法快速记录出现次数的问题

class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> mp;
int count = 0, pre = 0;
mp[0] = 1;
for (int i = 0; i < nums.size(); i++){
pre += nums[i];
if (mp.count(pre - k)) count += mp[pre-k];
mp[pre]++;
}
return count;
}
};

560.和为k的数组的更多相关文章

  1. 力扣 - 560. 和为K的子数组

    目录 题目 思路1(前缀和) 代码 复杂度分析 思路2(前缀和+哈希表优化) 代码 复杂度分析 题目 560. 和为K的子数组 思路1(前缀和) 构建前缀和数组,可以快速计算任意区间的和 注意:计算区 ...

  2. 【LeetCode】560. 和为K的子数组

    560. 和为K的子数组 知识点:数组:前缀和: 题目描述 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 输入:nums = [1,1,1], k = 2 ...

  3. Java实现 LeetCode 560 和为K的子数组(某著名排序大法改编)

    560. 和为K的子数组 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 1 : 输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] ...

  4. 转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中

    转:http://www.itmian4.com/thread-6504-1-1.html 最小区间原题 k个有序的数组,找到最小的区间范围使得这k个数组中,每个数组至少有一个数字在这个区间范围内.比 ...

  5. Leetcode 560.和为k的子数组

    和为k的子数组 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 1 : 输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1 ...

  6. LeetCode 560. 和为K的子数组(Subarray Sum Equals K)

    题目描述 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 1 : 输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1,1] ...

  7. 560. 和为K的子数组

    Q: A: 1.暴力找所有可能的子数组,n^2个子数组,最长长度n,则n ^3. 2.n^2解法 从1~n-1各起点开始,一直找到结尾,n^2 class Solution { public: int ...

  8. LeetCode——560. 和为K的子数组

    给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 1 : 输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1,1] 为两种不 ...

  9. 力扣题解-560. 和为K的子数组

    题目描述 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 1 : 输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1,1] ...

  10. 力扣Leetcode 560. 和为K的子数组

    和为K的子数组 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数. 示例 : 输入:nums = [1,1,1], k = 2 输出: 2 , [1,1] 与 [1,1 ...

随机推荐

  1. 浅谈数字孪生和GIS融合的必要性

    随着科技的不断发展和应用的不断深入,数字孪生和GIS在各自领域中展现出巨大的潜力.然而,更引人注目的是,数字孪生和GIS的融合将为许多行业带来全新的机遇和变革.在本文中,我们将探讨数字孪生和GIS融合 ...

  2. Android学习--Intent

    Intent : Intent 是一个动作的完整描述,一种运行时的绑定机制,Intent中包含对Intent有兴趣的组件信息,如对动作的产生组件.接受组件和传递的数据信息.Android根据此Inte ...

  3. uniapp中实现H5录音和上传、实时语音识别(兼容App小程序)和波形可视化

    目录 Recorder-UniCore插件特性 集成到项目中 调用录音 上传录音 ASR语音识别 在uniapp中使用Recorder-UniCore插件可以实现跨平台录音功能,uniapp自带的re ...

  4. 从VMWare安装到Nginx配置

    1.安装VMWare Workstation 16 player,Mac也可使用Parallels Desktop,自己有虚拟主机的跳过: 2.在虚拟机中,安装Centos7操作系统,使用Minima ...

  5. curl使用小记(四)——在多线程中使用的问题总结

    目录 1. 概述 2. 详论 2.1. 崩溃 2.2. 初始化 2.3. 性能 3. 参考 1. 概述 很显然,通过URL传输数据是一个耗费性能的行为.所以,一个非常有必要的策略是通过多线程来加快数据 ...

  6. Python中的cls语法

      在Python中,cls 是一个用于指代类本身的约定性名称,通常用作类方法(class method)中的第一个参数.cls 类似于 self,它是对类的引用,而不是对实例的引用.cls 通常在类 ...

  7. 一颗红心,三手准备,分别基于图片(img)/SCSS(样式)/SVG动画实现动态拉轰的点赞按钮特效

    华丽炫酷的动画特效总能够让人心旷神怡,不能自已.艳羡之余,如果还能够探究其华丽外表下的实现逻辑,那就是百尺竿头,更上一步了.本次我们使用图片.SCSS样式以及SVG图片动画来实现"点赞&qu ...

  8. 大数据场景下Volcano高效调度能力实践

    摘要:本篇文章将会从Spark on Kubernetes 发展历程以及工作原理,以及介绍一下Spark with Volcano,Volcano如何能够帮助 Spark运行地更高效. Spark o ...

  9. 跟我读论文丨ACL2021 NER BERT化隐马尔可夫模型用于多源弱监督命名实体识别

    摘要:本文是对ACL2021 NER BERT化隐马尔可夫模型用于多源弱监督命名实体识别这一论文工作进行初步解读. 本文分享自华为云社区<ACL2021 NER | BERT化隐马尔可夫模型用于 ...

  10. Git hooks与自动化部署

    好的 commit message 是至关重要的,如果随意编写 log,带来的后果可小可大,但是无论大小都影响了开发的效率和回朔的难度,所以有必要进行 log 规范化检查. 通过自定义的commit ...