Leetcode热题100:子串

Leetcode 560. 和为k的子数组

暴力解法:

这道题的暴力解法非常通俗易懂,我们既然要找和为k的子数组的个数,那么我们只需要检查一遍所有的子数组就好了,所以两层循环然后时间复杂度是O(n^2)

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        res = 0
        for i in range(len(nums)):
            cur_sum = 0
            for j in range(i, len(nums)):
                cur_sum = cur_sum + nums[j]
                if cur_sum == k:
                    res = res + 1
        
        return res
哈希表前缀和解法:

这里如果想要把时间复杂度降低到O(n)的话我们需要只遍历数组一遍,怎么去实现呢,就是用哈希表来记录一些有用的信息,然后来避免用循环浪费时间去找我们已经可以获取的信息,在这里就是我们在记录从第一个子数组然后慢慢扩大到整个数组的过程中,记录下来他们的和,每一次我们扩展到新的长度时,我们check当前这个数组和target的差距是否在之前的连续数组中的和相等,如果相等的话证明我们可以得到count个数的子数组能够帮助我们去得target

就像这个图中举的例子,当我们遍历到[1, -1, 1, 1, 1] 的时候,我们的sum就是k,这时候需要的之前数组能给我们的值就是3-3 = 0,我们在哈希表中发现符合这个条件的子数组有两个,证明当前数组 - 这两个子数组其中任意一个 = 一个符合题目条件的子数组,这里就是 [1, -1, 1, 1, 1] 和 [1, 1, 1] 这里的第一个数组就是我们这个方法的一个edge case,在哈希表创建的时候,我们就应该在prefix 0 里面的count = 1,我们遍历结束的时候,刚好整个数组的和就是k,也就是我们要找prefix = 0 的count是多少,我们这时候需要他是1

接下来我们遍历到 loop 6 的时候,我们需要的是能够提供prefix是1 的子数组来使当前数组 - prefix是1的数组 = 符合条件的数组,也就是 [1, -1, 1, 1, 1, 1] 和 [1, 1, 1] 注意这里的111的下标是3, 4, 5 和上一个循环的不一样

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        # create the hash table and sum variable and result
        prefix_count = {0: 1}
        prefix_sum = 0
        res = 0

        # loop through the list to increase the current sublist until full
        for num in nums:
            prefix_sum = prefix_sum + num

            # calculate the diff as the num that the prefix sum need to reach k
            need = prefix_sum - k

            # see if we do have the need in the prefix_sum hash table from previous sublist
            # we visited, if so add its count to res and we add this prefix_sum's count 
            if need in prefix_count.keys():
                res = res + prefix_count[need]
            prefix_count[prefix_sum] = prefix_count.get(prefix_sum, 0) + 1

        return res

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值