Leetcode | 560. 和为 K 的子数组

news2025/1/10 16:32:05

560. 和为 K 的子数组

文章目录

  • [560. 和为 K 的子数组](https://leetcode.cn/problems/subarray-sum-equals-k/)
    • 题目
    • 解法1:暴力枚举
    • 解法2:前缀和
    • 解法3:[官方题解](https://leetcode.cn/problems/subarray-sum-equals-k/solutions/238572/he-wei-kde-zi-shu-zu-by-leetcode-solution/)

欢迎关注公众号“三戒纪元”

题目

给你一个整数数组 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

解法1:暴力枚举

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int count = nums.size();
        if(count == 0) {
            return 0;
        }

        int match = 0;
        for(int i = 0; i < count; ++i) {
            int sum = 0;
            for(int j = i; j < count; ++j) {超时
                sum += nums[j];
                if(sum == k) {
                    ++match;
                }
            }
        }
        return match;
    }
};

但是这种解法对于计算包含N个1和N个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;
    }
};

作者:力扣官方题解
链接:https://leetcode.cn/problems/subarray-sum-equals-k/solutions/238572/he-wei-kde-zi-shu-zu-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解法2:前缀和

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int count = nums.size();
        if(count == 0) {
            return 0;
        }
        sums.resize(count + 1, 0);

        int match = 0;
        for(int i = 0; i < count; ++i) {
            int sum = 0;
            for(int j = i; j >= 0; --j) {
                sum += nums[j];
                if(sum == k) {
                    ++match;
                }
            }
        }
        return match;
    }

    vector<int> sums;
};

同样会超时。

解法3:官方题解

我们可以基于方法一利用数据结构进行进一步的优化,我们知道方法一的瓶颈在于对每个 iii,我们需要枚举所有的 jjj 来判断是否符合条件,这一步是否可以优化呢?答案是可以的。

我们定义 p r e [ i ] pre[i] pre[i] [ 0.. i ] [0..i] [0..i] 里所有数的和,则 p r e [ i ] pre[i] pre[i] 可以由 p r e [ i − 1 ] pre[i−1] pre[i1] 递推而来,即:

p r e [ i ] = p r e [ i − 1 ] + n u m s [ i ] pre[i]=pre[i−1]+nums[i] pre[i]=pre[i1]+nums[i]

那么「 [ j . . i ] [j..i] [j..i] 这个子数组和为 k 」这个条件我们可以转化为
p r e [ i ] − p r e [ j − 1 ] = = k pre[i]−pre[j−1]==k pre[i]pre[j1]==k
简单移项可得符合条件的下标 jjj 需要满足
p r e [ j − 1 ] = = p r e [ i ] − k pre[j−1]==pre[i]−k pre[j1]==pre[i]k
所以我们考虑以 i 结尾的和为 k 的连续子数组个数时只要统计有多少个前缀和为 p r e [ i ] − k pre[i]−k pre[i]k p r e [ j ] pre[j] pre[j]即可。我们建立哈希表 m p mp mp,以和为键,出现次数为对应的值,记录 p r e [ i ] pre[i] pre[i]出现的次数,从左往右边更新 m p mp mp 边计算答案,那么以 iii 结尾的答案 m p [ p r e [ i ] − k ] mp[pre[i]−k] mp[pre[i]k]即可在 O ( 1 ) O(1) O(1) 时间内得到。最后的答案即为所有下标结尾的和为 k的子数组个数之和。

需要注意的是,从左往右边更新边计算的时候已经保证了 m p [ p r e [ i ] − k ] mp[pre[i]−k] mp[pre[i]k]里记录的$ pre[j]$的下标范围是 0 ≤ j ≤ i 0≤j≤i 0ji 。同时,由于 p r e [ i ] pre[i] pre[i] 的计算只与前一项的答案有关,因此我们可以不用建立$ pre$ 数组,直接用 p r e pre pre变量来记录 p r e [ i − 1 ] pre[i−1] pre[i1] 的答案即可。

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

        int match = 0;
        int pre = 0;
        for(int &num : nums) {
            pre += num;
            if(mp.find(pre - k) != mp.end() ) {
                match += mp[pre - k];
            }
            mp[pre]++;
        }
        return match;
    }

};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1037725.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

成都直播基地火热招商中,天府蜂巢成都直播基地招商政策汇总

随着直播产业的发展,四川天府新区也在逐步形成成熟的直播产业链。近日,记者采访到成都天府蜂巢直播产业基地即将竣工,正式进入运营阶段&#xff0c;作为成都科学城兴隆湖高新技术服务产业园的主打新一代成都直播基地&#xff0c;正积极招商中&#xff01;引领大规模的平台聚合发…

关于POM声明为provided的依赖,运行程序时报错NoClassDefFoundError

问题叙述 我在编写flink程序时&#xff0c;将flink相关依赖声明为provided&#xff08;目的是项目打包时不会将flink依赖打入包最终jar包中&#xff0c;减少内存占用&#xff09; 但是如果在IDEA本地中执行程序会报错java.lang.NoClassDefFoundError&#xff0c;如下所示 解…

静态资源的动态引入

有常用的2种方式&#xff1a; 1、css中的静态路径 2、img中的src静态路径 运行的环境是打包后的图片路径&#xff0c;而打包后的图片通常会生成一个文件指纹&#xff0c;而我们在写代码时&#xff0c;写的是源码中的路径和文件名&#xff0c;如果是静态路径&#xff0c;则会自动…

leetcodetop100(18) 螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#xff1a;matrix [[1,2,3…

SpringBoot启用禁用员工/员工分页查询/编辑员工 --苍穹外卖day3

启用禁用员工 Controller 路径参数前面加上Path~注解来获取参数 PostMapping("/status/{status}") ApiOperation("启用禁用员工") public Result StartOrStop(PathVariable("status") Integer status, Long id){log.info("启用禁用")…

你需要知道DDD基本知识

0 概述 2004 年埃里克埃文斯&#xff08;Eric Evans&#xff09;发表了《领域驱动设计》&#xff08;Domain-Driven Design –Tackling Complexity in the Heart of Software&#xff09;这本书&#xff0c;从此领域驱动设计&#xff08;Domain Driven Design&#xff0c;简称…

马尔可夫链预测 (Markov Chain)

一、人寿保险案例(两状态&#xff09; 人寿保险公司把人的健康状态分为健康和疾病两种&#xff0c;以一年为一个时段&#xff0c;研究健康状态的转变。假设对某一年龄段的人来说&#xff0c;今年健康&#xff0c;明年继续保持健康的概率为0.8&#xff0c;即明年转为疾病的概率…

网络协议定制

目录 一、协议定制 1.再谈协议 2.认识序列化与反序列化 二、网络计算器 1.序列化与反序列化头文件 2.服务端 3.客户端 4.makefile 5.运行结果 三、json序列化与反序列化 1.常用序列化与反序列化库 2.安装 3.使用 &#xff08;1&#xff09;Request的序列化 &…

39.动画动作菜单

特效 源码 index.html <!DOCTYPE html> <html> <head> <title>Animated Action Menu</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body><div class=&quo…

功能测试自动化测试流程

1概述 本流程是描述软件功能自动化测试过程中的步骤、内容与方法&#xff0c;明确各阶段的职责、活动与产出物。 2流程活动图 3活动说明 3.1测试计划&#xff08;可选&#xff09; 与以前的测试计划过程一致&#xff0c;只是在原来的测试计划中&#xff0c;添加对项目实施自动…

4、SpringBoot_Mybatis、Druid、Juint整合

五、SSM整合 1.整合Mybatis 1.1springmvc 整合回顾 导入坐标 <dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.17.RELEASE</version></dependency><dependency>…

力扣刷题-链表-两两交换链表中的节点

24.两两交换链表中的节点 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 解题思路 采用正常模拟的方法。 建议使用虚拟头结点&#xff0c;这样会方便很多&am…

大数据从入门到精通(超详细版)之BI工具的安装

前言 嗨&#xff0c;各位小伙伴&#xff0c;恭喜大家学习到这里&#xff0c;不知道关于大数据前面的知识遗忘程度怎么样了&#xff0c;又或者是对大数据后面的知识是否感兴趣&#xff0c;本文是《大数据从入门到精通&#xff08;超详细版&#xff09;》的一部分&#xff0c;小…

iMAP——论文解析

iMAP: Implicit Mapping and Positioning in Real-Time iMAP 是第一个提出用 MLP 作为场景表征的实时 RGB-D SLAM。iMAP 采用关键帧结构和多进程&#xff0c;通过动态信息引导的像素采样来提高速度&#xff0c;跟踪频率为 10 Hz&#xff0c;全局地图更新频率为 2 Hz。隐式 MLP…

Vite打包时使用plugin解决浏览器兼容问题

一、安装Vite插件 在终端输入如下命令&#xff1a; npm add -D vitejs/plugin-legacy 二、配置config文件 在项目目录下创建vite.config.js文件夹&#xff0c;配置如下代码&#xff1a; import { defineConfig } from "vite"; import legacy from "vitejs/pl…

VM虚拟机克隆

VMware 克隆虚拟机具有以下优点&#xff1a; 快速部署&#xff1a;通过克隆虚拟机&#xff0c;可以快速创建新的虚拟机副本&#xff0c;而无需从头开始进行操作系统和应用程序的安装。这节省了大量的时间和工作量。一致性和稳定性&#xff1a;克隆虚拟机是通过复制现有虚拟机来…

DeepMind: 用ReLU取代Softmax可以让Transformer更快

注意力是人类认知功能的重要组成部分&#xff0c;当面对海量的信息时&#xff0c;人类可以在关注一些信息的同时&#xff0c;忽略另一些信息。当计算机使用神经网络来处理大量的输入信息时&#xff0c;也可以借鉴人脑的注意力机制&#xff0c;只选择一些关键的信息输入进行处理…

常见限流算法学习

文章目录 常见限流算法学习前言限流算法基本介绍固定窗口计数器限流算法计数器限流算法相关介绍计数器限流算法的实现&#xff08;基于共享变量&#xff09;计数器限流算法的实现&#xff08;基于Redis&#xff09; 滑动窗口计数器算法滑动时间窗口算法相关介绍介绍滑动时间窗口…

【软件设计师-从小白到大牛】上午题基础篇:第五章 结构化开发方法

文章目录 前言结构化设计1、基本原则真题链接2、内聚与耦合真题链接3、系统结构/模块结构真题链接用户界面设计的黄金原则&#xff08;补充&#xff09;真题链接数据流图&#xff08;补充&#xff09;真题链接系统文档&#xff08;补充&#xff09;真题链接 前言 ​ 本系列文章…

如何使用 Git 进行多人协作开发(全流程图解)

文章目录 分支管理策略1.什么是Feature Branching&#xff1f;2.Feature Branching如何工作&#xff1f; 多人协作一&#xff1a;单分支1.准备工作2.创建分支3.在分支上开发4.分支合并5.清理 多人协作二&#xff1a;多分支1.创建分支2.在分支上开发3. pull request4.清理 在软件…