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

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

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

相关推荐
alexwang2111 小时前
B2007 A + B 问题 题解
c++·算法·题解·洛谷
重生之后端学习1 小时前
46. 全排列
数据结构·算法·职场和发展·深度优先·图论
wostcdk2 小时前
数论学习1
数据结构·学习·算法
我是中国人哦(⊙o⊙)2 小时前
我的寒假作业
人工智能·算法·机器学习
.格子衫.2 小时前
030动态规划之树形DP——算法备赛
算法·动态规划
胡萝卜不甜3 小时前
算法宗门--冒泡排序(“懒”到极致的算法)
算法
charliejohn3 小时前
计算机考研 408 数据结构 中缀转后缀
数据结构·考研·算法
lifallen3 小时前
后缀数组 (Suffix Array)
java·数据结构·算法
仰泳的熊猫3 小时前
题目1523:蓝桥杯算法提高VIP-打水问题
数据结构·c++·算法·蓝桥杯