当前位置: 首页 > news >正文

560. 和为 K 的子数组

题目

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 2 * 10^4
  • -1000 <= nums[i] <= 1000
  • -10^7 <= k <= 10^7

代码

完整代码

代码1

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>int subarraySum(int* nums, int numsSize, int k) {int count = 0;int prefixSum = 0;int minPrefixSum = 0;int maxPrefixSum = 0;// 计算所有可能的前缀和的最小值和最大值for (int i = 0; i < numsSize; i++) {prefixSum += nums[i];if (prefixSum < minPrefixSum) {minPrefixSum = prefixSum;}if (prefixSum > maxPrefixSum) {maxPrefixSum = prefixSum;}}// 计算哈希表的大小并分配内存int size = maxPrefixSum - minPrefixSum + 1;int* prefixSumCount = (int*)calloc(size, sizeof(int));if (!prefixSumCount) {return -1; // 内存分配失败}// 初始化prefixSumCount[-minPrefixSum] = 1; // 对应于前缀和为0的情况prefixSum = 0;// 遍历数组,计算前缀和并更新哈希表for (int i = 0; i < numsSize; i++) {prefixSum += nums[i];int target = prefixSum - k;if (target >= minPrefixSum && target <= maxPrefixSum) {count += prefixSumCount[target - minPrefixSum];}prefixSumCount[prefixSum - minPrefixSum]++;}// 释放内存free(prefixSumCount);return count;
}

代码2

int subarraySum(int* nums, int numsSize, int k) {if (numsSize == 1) {if (nums[0] != k) return 0;else return 1;}int* pHead = nums;int* pEnd = nums + 1;int cnt = (*pHead) == k;int nowSum = *pHead;while (pEnd < nums + numsSize) {nowSum += *pEnd;if (nowSum == k) {cnt++;}pEnd++;if ((pEnd == nums + numsSize) /* 到了数组末尾 */ && (pHead != nums + numsSize - 1) /* 头节点不在数组末尾 */) {pHead++;pEnd = pHead + 1;nowSum = *pHead;cnt += ((*pHead) == k);}}return cnt;
}

思路分析

对于这道题,我们需要统计数组中和为 k 的子数组个数。可以用前缀和加哈希表的方法,也可以用双指针法。下面详细介绍这两种方法。

方法一:前缀和 + 哈希表

  1. 初始化变量

    • count 用于记录和为 k 的子数组个数。
    • prefixSum 用于记录当前前缀和。
    • minPrefixSummaxPrefixSum 用于记录前缀和的最小值和最大值。
  2. 计算前缀和的范围

    • 遍历数组,计算所有可能的前缀和的最小值和最大值。
  3. 使用哈希表存储前缀和出现的次数

    • 计算哈希表的大小,并分配内存。
    • 初始化哈希表,对应前缀和为 0 的情况。
    • 遍历数组,计算前缀和并更新哈希表。
  4. 统计和为 k 的子数组个数

    • 如果 target 在前缀和的范围内,则累加 count
    • 更新当前前缀和的计数。
  5. 释放内存

方法二:双指针法

  1. 初始化指针和变量

    • 使用两个指针 pHeadpEnd
    • 变量 cnt 用于记录和为 k 的子数组个数。
    • 变量 nowSum 用于记录当前子数组的和。
  2. 遍历数组

    • 使用双指针遍历数组,计算子数组的和。
    • 如果当前子数组和为 k,则累加 cnt
    • 当遍历到数组末尾且 pHead 不在数组末尾时,移动 pHead,并更新 pEndnowSum
  3. 返回结果

复杂度分析

方法一:前缀和 + 哈希表

  • 时间复杂度:O(n),其中 n 是数组的长度。我们遍历数组两次,第一次计算前缀和范围,第二次更新哈希表并统计结果。
  • 空间复杂度:O(n),我们使用了一个哈希表来存储前缀和的次数。

方法二:双指针法

  • 时间复杂度O(n^2),其中n是数组的长度。最坏情况下,双指针遍历数组的时间复杂度为 O(n^2)
  • 空间复杂度O(1),我们只使用了常量级别的额外空间。

结果

方案1

在这里插入图片描述

方案2

在这里插入图片描述

相关文章:

  • RoCE网络架构在高性能计算的应用
  • [Golang] go-kit 介绍和使用 (微服务实现工具)
  • 【漏洞复现】飞企互联-FE企业运营管理平台 treeXml.jsp SQL注入漏洞
  • 【每日刷题】Day66
  • Web前端开发12章:深入探索与实战解析
  • Elixir学习笔记——输入输出和文件系统
  • React组件通信方式总结
  • Golang学习笔记01
  • CMU最新论文:机器人智慧流畅的躲避障碍物论文详细讲解
  • 卡尔曼滤波原理及应用(一)
  • Web前端后端架构:构建高效、稳定与可扩展的互联网应用
  • cnvd_2015_07557-redis未授权访问rce漏洞复现-vulfocus复现
  • 【0基础学爬虫】爬虫基础之自动化工具 DrissionPage 的使用
  • vite-plugin-mock前端自行模拟接口返回数据的插件
  • PHP开发的爱情盲盒交友系统网站源码
  • [数据结构]链表的实现在PHP中
  • 【前端学习】-粗谈选择器
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • cookie和session
  • ES学习笔记(12)--Symbol
  • iOS 系统授权开发
  • JavaScript 一些 DOM 的知识点
  • laravel with 查询列表限制条数
  • laravel 用artisan创建自己的模板
  • Linux gpio口使用方法
  • miaov-React 最佳入门
  • nginx 负载服务器优化
  • redis学习笔记(三):列表、集合、有序集合
  • REST架构的思考
  • Spring Boot MyBatis配置多种数据库
  • Vue2 SSR 的优化之旅
  • WebSocket使用
  • 初识 beanstalkd
  • 订阅Forge Viewer所有的事件
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 技术发展面试
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • Mac 上flink的安装与启动
  • 进程与线程(三)——进程/线程间通信
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #Linux(make工具和makefile文件以及makefile语法)
  • #pragma data_seg 共享数据区(转)
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $.each()与$(selector).each()
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (23)Linux的软硬连接
  • (c语言)strcpy函数用法
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (十)c52学习之旅-定时器实验
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (转)linux自定义开机启动服务和chkconfig使用方法