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

【每日一题】Day 7

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 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107


1. 暴力法

遍历数组的每个起点 i
从 i 开始,依次往后延伸,形成子数组 nums[i:j]
计算这个子数组的和
如果等于 k,计数器 +1


代码实现(Go):

//package main
//
//import "fmt"func subarraySum(nums []int, k int) int {cnt := 0 // 子数组个数// 外层循环:确定子数组起点 ifor i := 0; i < len(nums); i++ {sum := 0 // 初始化子数组和// 内层循环:确定子数组终点 jfor j := i; j < len(nums); j++ {sum += nums[j] // 累加子数组元素if sum == k {  // 如果子数组和等于 kcnt++ // 计数器 +1}}}return cnt
}//func main() {
//	nums1 := []int{1, 1, 1}
//	k1 := 2
//	fmt.Println(subarraySum(nums1, k1)) // 输出 2
//}

2. 前缀和 + 哈希表优化

前缀和的概念
使用一个叫做“前缀和”的概念。对于数组中的任何位置 j,前缀和 pre[j] 是数组中从第 1 个元素到第 j 个元素的总和。如果想知道从元素 i+1 到 j 的子数组的和,可以用 pre[j] - pre[i] 来计算。

使用 Map 来存储前缀和
在代码中,用一个 Map(哈希表)来存储每个前缀和出现的次数。这是为了快速检查某个特定的前缀和是否已经存在,以及它出现了多少次。

核心逻辑
在数组中向前移动时,逐步增加 pre(当前的累积和)对于每个新的 pre 值,检查 pre - k 是否在 Map 中

pre - k 的意义:这个检查的意义在于,如果 pre - k 存在于 Map 中,说明之前在某个点的累积和是 pre - k。由于当前的累积和是 pre,这意味着从那个点到当前点的子数组之和恰好是 k(因为 pre - (pre - k) = k)

实现

  1. 遍历数组,累加前缀和 pre[j]
    pre[j]=nums[0]+nums[1]+⋯+nums[j]

  2. 用哈希表记录每个前缀和出现的次数
    key = 前缀和
    value = 出现次数

  3. 对于当前前缀和 pre,查找 pre - k 是否在哈希表里

  4. 如果存在,说明从之前某个位置到当前位置的子数组和为 k

  5. 将出现次数累加到结果

代码实现(Go):

// package main// import "fmt"func subarraySum(nums []int, k int) int {cnt := 0           // 用来记录子数组的个数pre := 0           // 当前前缀和m := map[int]int{} // 或 m:=make(map[int]int)m[0] = 1           // 前缀和 0 出现 1 次,保证一个数字刚好等于 k 时,也能被正确统计,计数+1for i := 0; i < len(nums); i++ {pre += nums[i] // 更新当前前缀和// 查找 pre - k 是否出现过,如果出现,说明从之前的位置到当前位置之间的子数组和为 kif v, ok := m[pre-k]; ok {cnt += v}// 更新哈希表,记录当前前缀和出现次数m[pre]++}return cnt
}// func main() {
// 	nums1 := []int{1, 1, 1}
// 	k1 := 2
// 	fmt.Println(subarraySum(nums1, k1)) // 输出 2
// }

无注释:

//package main
//
//import "fmt"func subarraySum(nums []int, k int) int {cnt, pre := 0, 0m := map[int]int{}m[0] = 1for i := 0; i < len(nums); i++ {pre += nums[i]if v, ok := m[pre-k]; ok {cnt += v}m[pre]++}return cnt
}//func main() {
//	nums1 := []int{1, 1, 1}
//	k1 := 2
//	fmt.Println(subarraySum(nums1, k1)) // 输出 2
//}

http://www.dtcms.com/a/338086.html

相关文章:

  • Linux——进程间、线程间的通信
  • 【C++】 using声明 与 using指示
  • 《彩色终端》诗解——ANSI 艺术解码(DeepSeek)
  • C++设计模式:建造者模式
  • 《若依》权限控制
  • ESP32小智-语音活动(VAD)检测流程
  • Pytorch GPU版本安装保姆级教程
  • 【Python面试题】描述一次解决内存泄漏的过程。如何用tracemalloc或者objgraph定位问题?什么情况下会用__slots__?
  • 【领码课堂】AI写码不再“盲跑”,方案先行,自动化高效落地
  • BOSS直聘招聘端AI辅助自动化技术研究
  • 某储备土地前期开发项目控制保护区桥梁自动化监测
  • 8.19 note
  • HashMap:源码
  • OpenLayers 入门指南【七】:加载自定义控件
  • 部署耐达讯自动化Profibus转光纤方案,变频器通信从此告别‘掉线焦虑’!“
  • Next.js数据获取
  • 飞算JavaAI智慧文旅场景实践:从景区管理到游客服务的全链路系统搭建
  • 无人机激光测距技术应用与挑战
  • 【前端进阶】UI渲染优化 - 骨架屏技术详解与多框架实现方案
  • Maven(一)
  • 做一个答题pk小程序多少钱?
  • 《红色脉-络:一部PLMN在中国的演进史诗 (1G-6G)》 第6篇 | 专题:核心网的第一次革命——从电路交换到“用户/控制面分离”
  • java17学习笔记-增强型伪随机数生成器
  • LeetCode100-438找到字符串中所有的字母异位词
  • 上网行为管理之用户认证技术和应用控制技术
  • 开源im即时通讯软件开发社交系统全解析:安全可控、功能全面的社交解决方案
  • 具身智能3全身动力学控制软件包(人形机器人)摘自Openloong社区
  • N32G430C8-串口驱动问题
  • MATLAB的实用字母识别系统实现含GUI界面
  • 软件在线安装和离线安装