WELCOME TO Pluto134340小行星

清风湿润,茶烟轻扬。

10.和为K的子数组

LCR 010. 和为 K 的子数组

示例 1:

输入:nums = [1,1,1], k = 2
输出: 2
解释: 此题 [1,1] 与 [1,1] 为两种不同的情况

示例 2:

输入:nums = [1,2,3], k = 3
输出: 2
解释: [1,2] 与 [3] 为两种不同的情况

方法1: 暴力枚举

思路从start开始遍历,找到以start开始和为K的子数组。

 1 class Solution {
 2     public int subarraySum(int[] nums, int k) {
 3         int count = 0;
 4         for(int start = 0;start<nums.length; start++){
 5             int sum = 0;
 6             for(int i = start ;i<nums.length;i++){
 7                 sum+=nums[i];
 8                 if(sum == k){
 9                     count++;
10                 }
11             }
12         }
13         return count;
14     }
15 }
View Code

 

方法2:  前缀和+哈希表

我们定义 pre[i] 为 [0..i] 里所有数的和,则 pre[i] 可以由 pre[i−1] 递推而来,即:

                                    pre[i]=pre[i−1]+nums[i]
那么「[j..i] 这个子数组和为 k 」这个条件我们可以转化为

                                    pre[i]−pre[j−1]==k          

【为什么 j ~ i 减的是pre[j -1]  ,例如【1,1,1】k=2.  当i=1;j=0时候 正好满足, 但需要减 j -1,不然就减多了】
简单移项可得符合条件的下标 j 需要满足

                                    pre[j−1]==pre[i]−k

核心思路:

将当前位置的前缀和存入哈希,若存在+1,不存在赋值为1;

遍历 前缀和满足count+

class Solution {
    public int subarraySum(int[] nums, int k) {
        // 1. 初始化变量
        int count = 0, pre = 0; // count:最终结果(符合条件的子数组个数);pre:当前累计的前缀和
        HashMap<Integer ,Integer> map = new HashMap<>(); // key:前缀和值;value:该前缀和出现的次数
        map.put(0,1); // 关键:初始化前缀和0出现1次(对应pre[0]=0)
        
        // 2. 遍历数组,计算前缀和并统计
        for(int end = 0; end<nums.length; end++){
            pre += nums[end]; // 累加当前元素,得到「前end+1个元素的前缀和」(对应pre[end+1])
            
            // 3. 核心:查找是否存在 pre-k 的前缀和,存在则累加次数到count
            if(map.containsKey(pre-k)){
                count += map.get(pre-k); // 有多少个pre[j]=pre-k,就有多少个符合条件的子数组
            }
            
            // 4. 将当前前缀和存入哈希表(更新出现次数)
            map.put(pre, map.getOrDefault(pre, 0) + 1);
        }
        return count;
    }
}
View Code

image

os:有点绕,在理解理解吧

 

posted @ 2026-01-12 12:04  Pluto134340  阅读(22)  评论(0)    收藏  举报