news 2026/5/24 0:56:22

LeetCode 930:和相同的二元子数组 | 前缀和与哈希表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 930:和相同的二元子数组 | 前缀和与哈希表

LeetCode 930:和相同的二元子数组 | 前缀和与哈希表

引言

和相同的二元子数组(Binary Subarrays With Sum)是 LeetCode 第 930 题,难度为 Medium。题目要求在二元数组(元素只有 0 和 1)中找出子数组和等于 S 的数量。这道题与 LeetCode 560(和为 K 的子数组)非常相似,但因为数组是二元的,可以使用更高效的方法。

对于二元数组,我们可以使用"计数法"来优化:当 S 较大时,遍历所有子数组可能需要 O(n²) 时间;但使用哈希表方法仍然是 O(n)。另一种方法是使用"滑动窗口",因为数组是二元的,可以更高效地处理。

问题分析

题目描述

给定一个二元数组 nums 和一个整数 S,计算有多少个子数组的元素和等于 S。

例如,输入 nums = [1,0,1,0,1],S = 2,有 4 个子数组的和等于 2:

  • [1,0,1](索引 0-2)
  • [1,0,1](索引 2-4)
  • [0,1,0,1](索引 1-4)
  • [1](但这个和为 1,不是 2,所以只有前三个?)

实际上,正确答案是:

  • [1,0,1](索引 0-2):1+0+1=2
  • [1,0,1](索引 2-4):1+0+1=2
  • [1,0,1,0,1]的和是3,不是2

问题特点

因为数组是二元的,元素只能是 0 或 1。这使得我们可以使用更高效的方法。但核心思路仍然是前缀和与哈希表。

解决方案

前缀和哈希表方法

def numSubarraysWithSum(nums, s): prefix_sum = 0 count = 0 prefix_map = {0: 1} for num in nums: prefix_sum += num count += prefix_map.get(prefix_sum - s, 0) prefix_map[prefix_sum] = prefix_map.get(prefix_sum, 0) + 1 return count

这与 LeetCode 560 的解法完全相同。对于任意整数数组(包括二元数组),这个方法都适用。

计数方法(优化)

因为数组是二元的,我们可以使用更直接的方法。观察发现,对于子数组和为 S 的情况,子数组中必须恰好有 S 个 1。这 S 个 1 之间的 0 可以任意数量。

def numSubarraysWithSum_optimized(nums, s): def countAtMost(k): if k < 0: return 0 result = 0 left = 0 count = 0 for right in range(len(nums)): if nums[right] == 1: count += 1 while count > k: if nums[left] == 1: count -= 1 left += 1 result += right - left + 1 return result return countAtMost(s) - countAtMost(s - 1)

这个方法计算"至多 s 个 1"的子数组数量减去"至多 s-1 个 1"的子数组数量,得到恰好 s 个 1 的子数组数量。

算法正确性证明

计数方法的正确性

对于"至多 s 个 1"的子数组数量,使用滑动窗口方法计算。每次扩展右边界,统计以当前右边界结尾的满足条件的子数组数量(right - left + 1)。然后收缩左边界直到窗口内 1 的数量不超过 s。

减法原理:恰好 s 个 1 的子数组 = 至多 s 个 1 的子数组 - 至多 s-1 个 1 的子数组。

复杂度分析

哈希表方法

时间复杂度:O(n)
空间复杂度:O(n)

计数方法

时间复杂度:O(n)(两次遍历)
空间复杂度:O(1)

代码实现

Python 实现(哈希表)

def numSubarraysWithSum(nums, s): prefix_sum = 0 count = 0 prefix_map = {0: 1} for num in nums: prefix_sum += num count += prefix_map.get(prefix_sum - s, 0) prefix_map[prefix_sum] = prefix_map.get(prefix_sum, 0) + 1 return count

Python 实现(计数)

def numSubarraysWithSum_count(nums, s): def countAtMost(k): if k < 0: return 0 result = 0 left = 0 count = 0 for right in range(len(nums)): if nums[right] == 1: count += 1 while count > k: if nums[left] == 1: count -= 1 left += 1 result += right - left + 1 return result return countAtMost(s) - countAtMost(s - 1)

边界情况处理

S = 0

当 S = 0 时,需要统计和为 0 的子数组数量,即没有 1 的子数组。计数方法中的 countAtMost(-1) 会返回 0,countAtMost(0) 会正确计算没有 1 的子数组数量。

全 0 数组

当数组全为 0 时,子数组和都是 0。如果 S = 0,子数组数量是 n*(n+1)/2;如果 S > 0,子数组数量是 0。两种方法都能正确处理。

全 1 数组

当数组全为 1 时,子数组和等于子数组长度。计数方法使用滑动窗口,正确统计恰好 s 个 1 的子数组数量。

测试用例

def test_num_subarrays_with_sum(): assert numSubarraysWithSum([1,0,1,0,1], 2) == 4 assert numSubarraysWithSum([1,0,1,0,1], 0) == 4 assert numSubarraysWithSum([0,0,0,0,0], 0) == 15 assert numSubarraysWithSum([1,1,1,1], 2) == 3 assert numSubarraysWithSum([1], 0) == 0 assert numSubarraysWithSum([0], 0) == 1 assert numSubarraysWithSum([], 0) == 1 print("所有测试用例通过!")

总结

和相同的二元子数组问题展示了两种方法:通用的前缀和哈希表方法和针对二元数组优化的计数方法。两种方法都是 O(n) 时间复杂度,但计数方法空间复杂度更优(O(1) vs O(n))。

对于二元数组,计数方法利用了"恰好 s 个 1"的特性,通过计算"至多 s 个"和"至多 s-1 个"的差来得到精确答案。这种转换思路在处理"恰好"问题时很有用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/24 0:47:28

AI知识管理不是工具升级,而是教学主权重构:一位特级教师用18个月完成“教案→知识流→认知干预”三级跃迁(全程数据脱敏实录)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI知识管理在教育领域的应用 AI知识管理正深刻重塑教育生态&#xff0c;通过智能索引、语义理解与个性化推荐&#xff0c;将碎片化教学资源转化为可检索、可推理、可演化的结构化知识网络。教师可借助自…

作者头像 李华
网站建设 2026/5/24 0:45:13

3分钟搞定Windows桌面整理:NoFences免费开源工具终极指南

3分钟搞定Windows桌面整理&#xff1a;NoFences免费开源工具终极指南 【免费下载链接】NoFences &#x1f6a7; Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences 你是否每天都要在杂乱的Windows桌面上寻找文件&#xff…

作者头像 李华
网站建设 2026/5/24 0:37:12

书匠策AI:你的毕业论文“导航仪“已上线,全程带飞不迷路!

各位正在和毕业论文"死磕"的同学们&#xff0c;今天这篇内容&#xff0c;可能会刷新你对"写论文"这件事的认知。 先问大家一个扎心的问题&#xff1a;你写论文的时候&#xff0c;有没有一种在迷宫里转圈的感觉&#xff1f; 选题不会选&#xff0c;转圈&am…

作者头像 李华
网站建设 2026/5/24 0:37:09

深度解析VinXiangQi:基于YOLOv5的智能象棋辅助工具完全指南

深度解析VinXiangQi&#xff1a;基于YOLOv5的智能象棋辅助工具完全指南 【免费下载链接】VinXiangQi Xiangqi syncing tool based on Yolov5 / 基于Yolov5的中国象棋连线工具 项目地址: https://gitcode.com/gh_mirrors/vi/VinXiangQi VinXiangQi是一款革命性的中国象棋…

作者头像 李华
网站建设 2026/5/24 0:32:46

创业公司如何做好成本控制

创业公司如何做好成本控制 前言 创业初期&#xff0c;我们烧钱很快&#xff0c;但不知道钱都花哪儿了。直到有一天财务说&#xff1a;"账上的钱只够撑6个月了。" 从那以后&#xff0c;成本控制成为我每天都在思考的问题。今天&#xff0c;分享我们是如何建立成本控制…

作者头像 李华