力扣打卡 560-和为K的子数组

Problem: 560. 和为 K 的子数组

思路

首先想到的就是暴力枚举,每个元素都可能能成为子串的头部。

优化:前缀和+哈希表

解题方法

暴力枚举

  1. 使用两个指针 start end 来确定子数组的范围。
  2. 外层循环遍历所有可能的起始位置 start
  3. 内层循环通过增加 end 来扩展子数组范围,并计算当前子数组的和 sum
  4. 如果 sum 等于 k,则增加计数器count的值。

前缀和+哈希表

在遍历数组的过程中,我们计算当前的前缀和 preSum,然后检查是否存在一个之前的前缀和 preSum - k,如果存在,说明从该前缀和到当前位置的子数组和为 k,所以我们将其出现次数加到结果 res 中。

然后,我们更新哈希表 map,将当前前缀和 preSum 的出现次数加1。

最后,返回结果 res

复杂度

暴力枚举

  • 时间复杂度:
    O ( n 2 ) O(n^2) O(n2)

  • 空间复杂度:
    O ( 1 ) O(1) O(1)

前缀和+哈希

  • 时间复杂度:
    O ( n ) O(n) O(n)

  • 空间复杂度:
    O ( n ) O(n) O(n)

Code

暴力枚举

class Solution {
    public static int subarraySum(int[] nums, int k) {
        int n = nums.length;
        int count = 0;

        for (int start = 0; start < n; start++) {
            int sum = 0;
            for (int end = start; end < n; end++) {
                sum += nums[end]; // 计算当前子数组的和
                if (sum == k) {
                    count++; // 如果和等于 k,则增加计数
                }
            }
        }

        return count;
    }
}

前缀和+哈希表

class Solution {
    public static int subarraySum(int[] nums, int k) {
        //前缀和
        Map<Integer,Integer> map = new HashMap<>();
        map.put(0,1);
        int preSum = 0,res =0;
        for(int num:nums){
            preSum+=num;
            if(map.containsKey(preSum-k)){
                res+=map.get(preSum-k);
            }
            map.put(preSum,map.getOrDefault(preSum,0)+1);
        }
        return res;
    }
}

你可能感兴趣的:(leetcode,算法)