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))

思路

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

  1. int count = 0;
  2. for (int start = 0; start <= nums.size(); start++)
  3. {
  4. for (int end = start; end <= nums.size(); end++)
  5. {
  6. int sum = 0;
  7. for (int i = start; i <= end; i++)
  8. sum += nums[i];
  9. if (sum == k) count++;
  10. }
  11. }

但是这里的时间复杂度达到了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]也满足条件但是没有算上!!!

  1. class Solution {
  2. public:
  3. int subarraySum(vector<int>& nums, int k) {
  4. int count = 0;
  5. for (int start = 0; start < nums.size(); start++) {
  6. int sum = 0;
  7. for (int end = start; end >= 0; end--) {
  8. sum += nums[end];
  9. if (sum == k) {
  10. count++;
  11. }
  12. }
  13. }
  14. return count;
  15. }
  16. };

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即可

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

  1. class Solution {
  2. public:
  3. int subarraySum(vector<int>& nums, int k) {
  4. unordered_map<int, int> mp;
  5. int count = 0, pre = 0;
  6. mp[0] = 1;
  7. for (int i = 0; i < nums.size(); i++){
  8. pre += nums[i];
  9. if (mp.count(pre - k)) count += mp[pre-k];
  10. mp[pre]++;
  11. }
  12. return count;
  13. }
  14. };

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. 反向 Debug 了解一下?揭秘 Java DEBUG 的基本原理

    Debug 的时候,都遇到过手速太快,直接跳过了自己想调试的方法.代码的时候吧-- 一旦跳过,可能就得重新执行一遍,准备数据.重新启动可能几分钟就过去了. 好在IDE 们都很强大,还给你后悔的机会,可 ...

  2. 《HelloGitHub》第 93 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...

  3. Fiddler使用 抓取手机数据包及中文乱码解决方案

    https://blog.csdn.net/zyb2017/article/details/79260086

  4. JavaFx之场景交互(二十一)

    JavaFx之场景交互(二十一) 有parent.son两个父子窗口,父窗口可以操作子窗口,父子可以相互调用对方的对象,下面我给出两种方案,我推荐使用第二种 一.构造传参 参数比较多的话代码不优雅.而 ...

  5. Java 在PPT中添加文本、图片超链接

    本文介绍通过Java程序在PPT幻灯片中添加超链接的方法,可以给文本或者图片设置超链接,设置超链接时,可设置包括网页链接.邮件地址链接.幻灯片跳转链接等不同指向对象的链接.文中方法使用了免费版PPT类 ...

  6. 聆听无声的话语:手把手教你用ModelArts实现手语识别

    摘要:ModelArts,化作我们与听力障碍之间的一座沟通桥梁. 据统计,我国有超过2000万人有听力语言障碍,每年有约3万名婴儿生来就失去了聆听的机会.或许是因为缺少与没有听力障碍的人交流的途径,环 ...

  7. 厚积薄发!华为云7篇论文被AAAI收录,2021年AI行业技术风向标看这里!

    摘要:近期,全球人工智能领域的顶级学术会议AAAI 2021将于2月2日-9日在线上召开,华为云的7篇AI科研成果被收录. 全球人工智能领域的顶级学术会议AAAI 2021将于2月2日-9日在线上召开 ...

  8. 5步带你掌握工作流Activiti框架的使用

    摘要:本文通过一个工作流Activiti框架的具体使用示例,具体详尽的介绍了工作流Activiti框架的使用方式. 本文分享自华为云社区<一个使用示例,五个操作步骤!从此轻松掌握项目中工作流的开 ...

  9. 如何上传苹果ipa安装包?

    ​ 如何上传苹果ipa安装包? 引言 在将应用程序上架到苹果应用商店之前,开发者需要学习如何上传ipa安装包.本文将介绍使用appuploader工具将ipa安装包上传到苹果应用商店的详细步骤,并提供 ...

  10. 最高提升10倍性能!揭秘火山引擎ByteHouse查询优化器实现方案

     更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   作为企业级数据库的核心组件之一,查询优化器的地位不可忽视.对于众多依赖数据分析的现代企业来说,一个强大且完善 ...