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

前缀和实战:和为 K 的子数组及整除子数组解法

前缀和结合哈希表是解决子数组统计问题的利器。详解 LeetCode 560 题与 974 题,核心逻辑是利用前缀和差值快速定位目标区间,并通过同余定理处理整除判定。针对负数取模场景,采用 (a%n+n)%n 技巧确保结果非负。整体方案将时间复杂度优化至 O(n),适合面试高频考点复习。

山野来信发布于 2026/3/28更新于 2026/10/2291 浏览
前缀和实战:和为 K 的子数组及整除子数组解法

前缀和专题实战

在算法面试中,涉及子数组求和的问题往往可以通过前缀和 + 哈希表的组合来优化。今天重点讲解两道经典题目:LeetCode 560(和为 K 的子数组)与 974(和可被 K 整除的子数组)。


1. 和为 K 的子数组

核心思路:

假设 sum[i] 表示从索引 0 到 i 的前缀和。如果我们想找到以 i 结尾、和为 k 的子数组,实际上是在寻找是否存在某个起始位置 x,使得 sum[i] - sum[x-1] == k。

移项后得到:sum[x-1] == sum[i] - k。

这意味着,我们不需要维护整个前缀和数组,只需要用一个哈希表记录遍历过程中每个前缀和出现的次数。当计算到当前位置的当前前缀和 currentSum 时,直接查询哈希表中 currentSum - k 出现过的次数即可。

注意点:

初始化时,哈希表中需放入 {0: 1}。这代表前缀和为 0 的情况出现过一次(即空数组),用于处理从数组开头开始就满足条件的情况。

代码实现:

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;
    }
};

时间复杂度 O(n),空间复杂度 O(n)。


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

这道题是上一题的变种,核心在于利用同余定理处理整除条件。

前置知识:

如果 (a - b) % n == 0,则 a % n == b % n。也就是说,两个数相减能被 n 整除,等价于它们对 n 取模的结果相同。

对于负数取模,C++ 中的 % 运算符可能返回负值(例如 -1 % 3 = -1)。为了保证结果非负,统一使用公式:(a % n + n) % n。

解题逻辑:

设 sum[i] 为当前前缀和。若子数组 [x, i] 的和能被 k 整除,则 sum[i] - sum[x-1] 必须是 k 的倍数。 根据同余定理,这等价于 sum[i] % k == sum[x-1] % k。

因此,我们只需统计之前出现过的、与当前前缀和同余(模 k 相等)的次数。

代码实现:

class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        unordered_map<int, int> hash;
        hash[0] = 1; // 初始前缀和为 0,余数为 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)。在处理整除问题时,务必注意负数取模的特殊性,这是容易踩坑的地方。掌握这个模式,能解决大量类似的子数组统计问题。

目录

  1. 前缀和专题实战
  2. 1. 和为 K 的子数组
  3. 2. 和可被 K 整除的子数组

更多推荐文章

查看全部
  • Linux 信号保存机制详解
  • 自然语言处理在教育领域的实战应用
  • C++ 网络模块兼容性优化的 7 个关键步骤
  • Seedance 2.0 实测:影视级 AI 视频生成的商业化落地
  • Paper Minecraft V3.0 下界更新:基于 C++ 的 2D 控制台版我的世界实现
  • Java 后端转 Web3 实战路线图
  • Harness Engineering:AI Agent 时代软件工程的范式转变
  • 算法题:接雨水问题详解与动态规划解法
  • 大型语言模型结构分类详解
  • 大模型时代企业转型:RAG 技术的演进与实践挑战
  • C++ 异常处理机制:异常捕获、自定义异常与实战应用
  • Go 语言信用卡号码 Luhn 算法校验实现
  • RTX50 系显卡与 CUDA、PyTorch、Python 版本对应关系整理
  • Python 学习资源推荐:Real Python 平台使用指南
  • 商汤开源 SenseNova-MARS:多模态搜索推理模型突破
  • 即梦 AI 基础操作指南:快速上手绘画与视频生成
  • Java 9 至 Java 25:语言演进与技术革新深度解析
  • Prometheus 进阶实战:MySQL、Nginx 与 Memcached 监控部署
  • Python 学习路线图与核心技术栈详解
  • OpenClaw 多平台卸载指南(Windows/macOS/Linux/npm/pnpm)

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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