跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

算法实战:和为 K 的子数组与和可被 K 整除的子数组

前缀和技巧配合哈希表是解决子数组求和问题的高效方案。本文详解了两道经典算法题:和为 K 的子数组以及和可被 K 整除的子数组。核心思路是利用前缀和差值关系,将区间和问题转化为查找特定前缀和或余数的问题。第一题直接寻找 sum[i] - k 的历史出现次数;第二题基于同余定理,寻找模 K 余数相同的累积和。代码实现中需特别注意 C++ 负数取模的处理方式,使用 (sum % k + k) % k 确保余数非负。整体方案将时间复杂度优化至 O(n),适合面试高频考察场景。

Stephaine Walsh发布于 2026/3/21更新于 2026/8/1859 浏览
算法实战:和为 K 的子数组与和可被 K 整除的子数组

前缀和专题实战

29. 和为 K 的子数组

题目链接: 560. 和为 K 的子数组 - LeetCode

题目描述

给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。

文章配图

示例

输入:nums = [1,1,1], k = 2 输出:2 解释:[1,1] 在索引 0-1 和 1-2 处各出现一次。

文章配图

解题思路

这道题的核心在于利用前缀和配合哈希表来优化查找效率。

想象一下,如果我们定义 sum[i] 为从下标 0 到 i 的所有元素之和。那么,任意区间 [x, i] 的和就可以表示为 sum[i] - sum[x-1]。

我们的目标是找到有多少个起始位置 x,使得 sum[i] - sum[x-1] == k。移项后得到: sum[x-1] == sum[i] - k

这意味着,当我们遍历到当前位置 i 时,只需要知道在 i 之前有多少个前缀和等于 当前前缀和 - k,就能确定以 i 结尾的满足条件的子数组数量。

为了高效查询,我们不需要维护一个完整的前缀和数组,而是用一个哈希表(unordered_map)记录每个前缀和出现的次数。一边计算当前前缀和,一边更新哈希表。

注意初始化 hash[0] = 1,这代表前缀和为 0 的情况出现了 1 次(即空数组),用于处理从数组开头就满足条件的情况。

代码实现

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> hash;
        hash[0] = 1; // 初始状态,前缀和为 0 出现 1 次
        int n = nums.size();
        int sum = 0, ret = 0;
        
        for (auto x : nums) {
            sum += x; // 累加当前前缀和
            if (hash.count(sum - k)) {
                ret += hash[sum - k]; // 累加符合条件的历史前缀和次数
            }
            hash[sum]++; // 更新当前前缀和的出现次数
        }
        return ret;
    }
};

30. 和可被 K 整除的子数组

题目链接: 974. 和可被 K 整除的子数组 - LeetCode

题目描述

给定一个整数数组 A,返回其中元素之和可被 K 整除的非空连续子数组的数目。

文章配图

前置知识补充

同余定理

如果 (a - b) % n == 0,则 a % n == b % n。 换句话说,如果两个数相减能被 n 整除,那么它们对 n 取模的结果相同。 例如:(26 - 2) % 12 == 0,则 26 % 12 == 2 % 12 == 2。

负数取模问题

C++ 中负数取模的结果可能为负。例如 -1 % 3 = -1。 为了确保结果始终为正,统一使用公式:(a % n + n) % n。 例如:(-1 % 3 + 3) % 3 = 2。

解题思路

这道题的思路与上一题类似,但需要处理整除条件。

设 sum[i] 为 [0, i] 区间的前缀和。若子数组 [x, i] 的和能被 K 整除,则: (sum[i] - sum[x-1]) % K == 0

根据同余定理,这等价于: sum[i] % K == sum[x-1] % K

也就是说,只要两个前缀和对 K 取模的余数相同,它们之间的子数组和就能被 K 整除。

我们需要统计在当前位置 i 之前,有多少个前缀和的余数与 sum[i] % K 相同。同样使用哈希表存储余数出现的次数。关键点是处理负数余数,确保存入哈希表的键都是非负的。

文章配图

代码实现

class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        unordered_map<int, int> hash;
        hash[0] = 1; // 余数为 0 的初始计数
        int sum = 0, ret = 0;
        
        for (auto x : nums) {
            sum += x;
            // 处理负数取模,确保余数在 [0, k-1] 范围内
            int r = (sum % k + k) % k;
            
            if (hash.count(r)) {
                ret += hash[r]; // 累加具有相同余数的历史前缀和次数
            }
            hash[r]++; // 更新当前余数的计数
        }
        return ret;
    }
};

总结

这两道题展示了前缀和技巧在子数组统计问题中的强大应用。通过引入哈希表,我们将时间复杂度从 O(n²) 优化到了 O(n)。特别是第二题,巧妙结合同余定理和负数取模处理,解决了看似复杂的整除判定问题。在实际编码中,注意边界条件(如初始值设置)和语言特有的取模行为,能避免很多潜在 Bug。

目录

  1. 前缀和专题实战
  2. 29. 和为 K 的子数组
  3. 题目描述
  4. 示例
  5. 解题思路
  6. 代码实现
  7. 30. 和可被 K 整除的子数组
  8. 题目描述
  9. 前置知识补充
  10. 同余定理
  11. 负数取模问题
  12. 解题思路
  13. 代码实现
  14. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • AI 赋能专利翻译,妙算翻译大模型亮相国际论坛
  • B/S 架构原理、技术栈选型与实战案例
  • Python 基础知识:字符串常用方法汇总
  • 拖延症:理解成因并建立可执行的行动策略
  • 双非毕业生如何成功入职阿里面试经验分享
  • Python 数据分析:数据预处理核心方法
  • 用 C 语言从零实现 Linux Shell:原理与实践
  • 在 Windows 上本地运行 DeepSeek 的 3 个步骤
  • PyCharm 安装通义灵码插件及功能使用指南
  • Python 中文繁简体转换工具 openccpy 使用指南
  • Qwen 3.5 MoE 本地部署指南:Ollama 快速运行与 API 调用
  • AM32 无人机电调源码架构与工作原理解析(上)
  • JDK 1.8 Windows 安装包下载及安装步骤
  • 多模态大模型的实现原理与技术难点
  • Whisper 语音识别技术:本地部署与使用指南
  • 电商产品 AI 绘画:高效提示词撰写实战指南
  • OpenClaw 部署飞书机器人
  • GitHub 智能客服机器人实战开发与性能优化
  • 俄罗斯方块游戏技术解析:从前端实现到工程化思考
  • 使用 Continue 插件本地部署 AI 代码助手替代 Cursor 或 Copilot

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online