leetcode算法15-和为K的子数组

题目:

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 

子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2
输出:2

示例 2:

输入:nums = [1,2,3], k = 3
输出:2

解法1:暴力枚举

代码:

class Solution {
    public int subarraySum(int[] nums, int k) {
        int count = 0;
        for (int i = 0; i < nums.length; i++) { // 枚举子数组的起始位置
            int sum = 0;
            for (int j = i; j < nums.length; j++) { // 枚举子数组的结束位置
                sum += nums[j]; // 累加从i到j的子数组的和
                if (sum == k) { // 如果子数组的和等于k
                    count++; // 计数器加1
                }
            }
        }
        return count; // 返回满足条件的子数组数量
    }
}

关键点:

1.思路,外循环固定起始值,内循环累计后面所有的值,满足条件,计数器加一。

解法2:前缀和+哈希表

代码:

class Solution {
    public int subarraySum(int[] nums, int k) {
        // 使用前缀和 + map 统计,和为 key,次数为 value
        Map<Integer, Integer> map = new HashMap<>();
        int pre = 0; // 当前前缀和
        map.put(pre, 1); // 初始化前缀和为 0 的情况
        int count = 0; // 满足条件的子数组数量

        for (int i = 0; i < nums.length; i++) {
            pre += nums[i]; // 更新当前前缀和
            // 先检查 pre - k 是否存在于 map 中
            if (map.containsKey(pre - k)) {
                count += map.get(pre - k); // 如果存在,说明有满足条件的子数组
            }
            // 再更新 map
            map.put(pre, map.getOrDefault(pre, 0) + 1);
        }

        return count;
    }
}

关键点:

1.思路:每次循环都记录前缀和,如果前缀和减去K有值存在,那说明之前就有满足条件的子数组。把统计的次数累加既是结果。

2.相关知识:

1. 前缀和的概念

前缀和是指从数组的起始位置到当前位置的所有元素的和。用pre表示当前的前缀和,那么对于任意位置ipre[i]表示从数组的起始位置到位置i的元素之和。

2. 子数组和的表示

假设我们有一个数组nums,我们需要找到所有子数组的和等于k。对于任意子数组nums[i:j](从位置i到位置j的子数组),其和可以表示为: sum(i:j)=pre[j]−pre[i−1] 其中:

  • pre[j]是从数组起始位置到位置j的前缀和。

  • pre[i-1]是从数组起始位置到位置i-1的前缀和。

如果子数组的和等于k,则有: pre[j]−pre[i−1]=k 即: pre[i−1]=pre[j]−k

3. 为什么使用count += map.get(pre - k);

在代码中,我们用map来存储每个前缀和pre出现的次数。当我们计算到当前的前缀和pre时,我们希望找到所有满足以下条件的前缀和pre[i-1]: pre[i−1]=pre−k

  • map.get(pre - k)的含义

    • map.get(pre - k)表示在当前前缀和pre之前,有多少个前缀和等于pre - k

    • 每一个这样的前缀和pre - k都对应一个满足条件的子数组。

  • count += map.get(pre - k)的作用

    • 如果map中存在pre - k,说明从这些前缀和到当前前缀和pre之间的子数组的和等于k

    • 因此,map.get(pre - k)的值表示满足条件的子数组的数量。

    • 将这个数量加到count中,可以统计所有满足条件的子数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值