LeetCode subarray-sum-equals-k题解 前缀和+Hash表+枚举——线性做法

本文介绍了一种高效算法,用于计算数组中连续子数组和等于特定值K的子数组数量。通过利用前缀和的概念和哈希表的数据结构,算法能够在O(n)的时间复杂度内解决问题。关键步骤包括维护前缀和的计数,以及快速查找满足条件的前缀和对。

题意

给定一个数组,求连续的子数组的和为k的子数组个数。

思路

连续子数组的和sum[i,j]

s u m [ i , j ] = ∑ k = i j A k ( i &lt; j ) sum[i,j]=\sum_{k=i}^jA_k(i&lt;j) sum[i,j]=k=ijAk(i<j)
即数组第i个数到第j个数的子数组的和。
s u m [ i , j ] = s u m [ j ] − s u m [ i − 1 ] sum[i,j]=sum[j]-sum[i-1] sum[i,j]=sum[j]sum[i1]其中 s u m [ i ] sum[i] sum[i]是前i个数的前缀和。
另子数组的和固定为k,则右边两个数只需要每一个,就可以确定另一个数的取值。
假设我们把前一个sum的下标记为r,后一个记为l.
若我们枚举l,我们有了如下需求:
sum数组中,下标大于l且值为sum[l]+k的个数是多少?
因此我们可以控制l的枚举顺序为从后往前,并且用hash表维护自l往后的sum[i]中的所有<sum值,个数>以应对此查询并且快速更新hash表。


同理,可以从前往后枚举r,用hash表维护下标小于r的所有的<sum值,个数>……

源码

class Solution {
    public int subarraySum(int[] nums, int k) {
        int len = nums.length;
        //key:sum,value:the count of sum[i] where i<r
        Map<Integer,Integer> map = new HashMap<Integer, Integer>();
        map.put(0,1); // sum[-1]=0
        int count = 0;
        for (int r = 0,r_sum = 0;r < len; ++r) {
            r_sum += nums[r];
            int l_sum = r_sum-k;
            if (map.containsKey(l_sum))
                count += map.get(l_sum);
            if (map.containsKey(r_sum))
                map.put(r_sum,map.get(r_sum)+1);
            else
                map.put(r_sum,1);
        }
        return count;
    }
}

结果记录

  • 19ms
  • 82.65%
  • 40.1MB
  • 100.0%
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值