leetcode560.和为k的子数组「前缀和&哈希」

127 篇文章 3 订阅
17 篇文章 0 订阅

1.题目描述

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

示例 1:

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

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

提示:

1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subarray-sum-equals-k
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.解题思路

转化问题为,求前缀和数组中后面任意一个数减去前面任意一个数等于k的对数有多少个

扫描一遍数组, 对每个i计算累计和sum并判断map内是否有sum-k,求前缀和数组中后面任意一个数减去前面任意一个数等于k的对数有多少个 ,相当于 求前缀和数组为sum-k的值有多少个,再使用map记录出现同样的和的次数

对于一开始的情况,下标 0 之前没有元素,可以认为前缀和为 0,个数为 1 个,因此,提前加入hashPreSum[0]=1

细节可以参考labuladong算法小抄 前缀和技巧
下面这个解法的时间复杂度 O(N^2) 空间复杂度 O(N) , 并不是最优的解法。
因此可以利用hash进行优化。

int subarraySum(int[] nums, int k) {
    int n = nums.length;
    // 构造前缀和
    int[] sum = new int[n + 1];
    sum[0] = 0;
    for (int i = 0; i < n; i++)
        sum[i + 1] = sum[i] + nums[i];
    int ans = 0;
    // 穷举所有⼦数组,注意i从1开始
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < i; j++)
            // sum of nums[j..i-1]
            if (sum[i] - sum[j] == k)
                ans++;
    return ans;
}

3.代码实现

class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        hashPreSum={}
        cur=0
        res=0
        # 前缀和本身等于k的情况
        hashPreSum[0]=1
        for num in nums:
            cur+=num
            # hash[cur-k] 为满足当前数cur减去前面cur-k等于k的情况数
            res+=hashPreSum.get(cur-k,0)
            hashPreSum[cur]=hashPreSum.get(cur,0)+1
        return res

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值