算法题解记录-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. 写在最后

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

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

相关推荐
To_OC2 小时前
LC 994 腐烂的橘子:人人都说是 BFS 入门题,我却写了三遍才过
javascript·算法·leetcode
金銀銅鐵5 小时前
[Python] 扩展欧几里得算法
python·数学·算法
To_OC8 小时前
LC 200 岛屿数量:经典 DFS 入门题,我第一次写居然连方向都搞错了
javascript·算法·leetcode
To_OC1 天前
LC 128 最长连续序列:别上来就排序,O (n) 解法才是这题的灵魂
javascript·算法·leetcode
05Kevin2 天前
lk每日冒险题--数据结构6.27
算法
To_OC2 天前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员
千纸鹤安安2 天前
千问Qwen-AgentWorld来了:一个语言模型搞定七大Agent场景,GPT-5.4都输了
算法
七牛开发者2 天前
MCP 到底是什么?为什么 Agent 都想接上它
算法·aigc·agent