算法题解记录-560和为k的子数组


🔍 LeetCode 560. 和为 K 的子数组 题解

📌 题目难度 :中等

📌 标签:数组、哈希表、前缀和


1. 问题理解

给定一个整数数组 nums 和一个整数 k,需要返回 连续子数组 中和为 k 的个数。

示例

复制代码
输入: nums = [1,1,1], k = 2
输出: 2
解释: [1,1] 出现两次(索引 0~1 和 1~2)

2. 从暴力解法出发

2.1 最直观的思路

我们可以枚举所有可能的连续子数组,计算它们的和,统计等于 k 的个数。

java 复制代码
int count = 0;
for (int i = 0; i < nums.length; i++) {
    for (int j = i; j < nums.length; j++) {
        int sum = 0;
        for (int m = i; m <= j; m++) {
            sum += nums[m];
        }
        if (sum == k) count++;
    }
}

时间复杂度:O(n³),不可接受。


3. 第一次优化:前缀和

3.1 什么是前缀和?

我们定义一个数组 pre,其中 pre[i] 表示从 nums[0]nums[i-1] 的和。

比如:

复制代码
nums = [1, 2, 3]
pre  = [0, 1, 3, 6]

那么子数组 nums[i..j] 的和 = pre[j+1] - pre[i]

3.2 优化后的暴力枚举

java 复制代码
int[] pre = new int[nums.length + 1];
for (int i = 0; i < nums.length; i++) {
    pre[i + 1] = pre[i] + nums[i];
}

int count = 0;
for (int i = 0; i < nums.length; i++) {
    for (int j = i; j < nums.length; j++) {
        if (pre[j + 1] - pre[i] == k) {
            count++;
        }
    }
}

时间复杂度:O(n²),依然可能超时。


4. 最终优化:前缀和 + 哈希表

4.1 思路转变

我们不再枚举所有子数组,而是 在遍历过程中,快速判断是否存在符合条件的起点

核心公式:

复制代码
pre[j+1] - pre[i] == k
等价于
pre[i] == pre[j+1] - k

也就是说,当我们遍历到 j 时,我们想知道有多少个 i 满足 pre[i] == pre[j+1] - k

4.2 用哈希表记录前缀和出现次数

我们可以在遍历数组的过程中:

  • 维护当前的前缀和 currentSum
  • 检查 currentSum - k 在之前出现过几次(即有多少个起点)
  • 每次将当前前缀和存入哈希表

4.3 代码实现

java 复制代码
public int subarraySum(int[] nums, int k) {
    // key: 前缀和, value: 出现次数
    Map<Integer, Integer> map = new HashMap<>();
    map.put(0, 1); // 初始状态:前缀和为0出现1次

    int currentSum = 0;
    int count = 0;

    for (int num : nums) {
        currentSum += num;

        // 如果存在 currentSum - k,说明找到了以当前结尾的子数组
        if (map.containsKey(currentSum - k)) {
            count += map.get(currentSum - k);
        }

        // 将当前前缀和存入哈希表
        map.put(currentSum, map.getOrDefault(currentSum, 0) + 1);
    }

    return count;
}

5. 为什么这样不会遗漏?

举个例子:

复制代码
nums = [1, 2, -2, 1, -1], k = 1
前缀和变化过程:
0 → 1 → 3 → 1 → 2 → 1

遍历到最后一个 -1 时,当前和为 1,currentSum - k = 0,哈希表中 0 出现了一次,说明从开头到当前位置的和为 1,正好符合条件。

我们一边遍历一边更新哈希表,相当于 固定了子数组的结尾,用哈希表快速查找符合条件的开头


6. 复杂度分析

  • 时间复杂度:O(n),只需遍历一次数组
  • 空间复杂度:O(n),哈希表存储前缀和

7. 总结

方法 时间复杂度 空间复杂度 说明
暴力枚举 O(n³) O(1) 不可行
前缀和 + 双重循环 O(n²) O(n) 可能超时
前缀和 + 哈希表 O(n) O(n) ✅ 最优解

核心思想:用空间换时间,通过哈希表快速查找目标前缀和


8. 写在最后

这道题是"前缀和"类题目的经典代表,也是面试中高频出现的题目之一。理解了这个思路,你就能轻松应对类似问题,比如:

如果这篇文章对你有帮助,欢迎点赞、收藏、转发~ 🚀

相关推荐
旖-旎1 小时前
深搜练习(单词搜索)(12)
c++·算法·深度优先·力扣
企客宝CRM2 小时前
2026年中小企业CRM选型指南:企客宝CRM处于什么位置?
android·算法·企业微信·rxjava·crm
橙淮2 小时前
二叉树核心概念与Java实现详解
数据结构·算法
米罗篮3 小时前
DSU并查集 & 拓展欧几里得-逆元
c++·经验分享·笔记·算法·青少年编程
橙淮3 小时前
双指针法:高效算法解题的利器
算法
初心未改HD3 小时前
深度学习之MLP与反向传播算法详解
人工智能·深度学习·算法
刀法如飞3 小时前
【Go 字符串查找的 20 种实现方式,用不同思路解决问题】
人工智能·算法·go
技术小黑5 小时前
CNN算法实战系列03 | DenseNet121算法实战与解析
pytorch·深度学习·算法·cnn
wearegogog1235 小时前
三电平SVPWM逆变器仿真指南
单片机·算法