概述
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
说明 :
数组的长度为 [1, 20,000]。
数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。
思路:看到这个首先想到用滑动窗口,但是最后还是没写出来,那就双层循环遍历呗,列举所有可能性,连续的前n项和等于k那子数组的个数就加1;这个方法的问题就在于:超出时间限制。说实话以前写算法没太考虑过时间限制,现在经常出现。那就说明时间复杂度太高了呗,这个暴力方法的时间复杂度是O(n²);那么就想办法怎么去降低这个时间复杂度。如果出现一个O(n)的算法就完全可以了;这个时候采用前缀和+哈希法。那么问题来了,什么是前缀和呢?
前缀和:从第0项到该项的和,举个栗子
0项到X项之和
F[x] = nums[0]+nums[1]+.........+nums[x]
num[x] = F[x]-F[x-1]
所以nums[i]到nums[j]总和:num[i]+....+nums[j] = F[j]-F[i-1]
所以这个题目可以转化成这样:F[j]-F[i-1]==k
当然这个题目转化成这样还是不性,为啥呢?因为有i和j。还是需要进行两层循环的,时间复杂度还没有变,看来前缀和势单力薄,还差点火候,那么此时上我的哈希。哈希在很多很多地方都有应用,之后写篇文章专门介绍哈希。其实在这里面我们根本不需要关注坐标,我们只在乎前缀和的值和出现的次数,这个时候建立哈希表,前缀和是键,出现的次数是值。其实就是看有多少前缀和是F[j]-k.最终就有几种情况。那么哈希表的初始话肯定是{0:1}.表示前缀和为0的出现了1次。
算法流程:
初始化哈希表(键:前缀和;值:出现次数)
遍历列表,计算前缀和,如果前缀和之前出现,加1就可;如果没出现那么就添加到哈希列表中去。
如果(前缀和-k)在哈希列表中,那么给计数器加1
此方法的时间复杂度和空间复杂度都是O(n),非常典型的一个空间换时间的一个题目。
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
'''
暴力法,超出时间限制
res = 0
for i in range(len(nums)):
Sum = 0
for j in range(i,len(nums)):
Sum+=nums[j]
if Sum==k:
res+=1
return res
'''
#声明一个hash表,在python中其实就是字典的数据结构
#默认键不存在的添加进去后value是1
num_times = collections.defaultdict(int)
#哈希表初始值是{0:1}
num_times[0] = 1
#前缀和
cur_sum = 0
#结果计数器
res = 0
for i in range(len(nums)):
cur_sum+=nums[i]
#如果前缀和-k在hash表中,那就更新计数器呗
if cur_sum-k in num_times:
res+=num_times[cur_sum-k]
#如果前缀和不在列表中的话就进行更新,已经存在的value+1;不存在的把key加入然后value设为1,因为coolection这个方法的特性,所以将两个和二为1了.
num_times[cur_sum]+=1
return res
此图来源leetcode官方解法:从左至右,从上到下;非常清晰的解释了hash+前缀和的方法
总结:前缀和+哈希是解决数组问题中非常重要的一个方法,也是空间换时间的一个非常好的栗子。
最后
以上就是内向小蚂蚁为你收集整理的560.和为K的子数组的全部内容,希望文章能够帮你解决560.和为K的子数组所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复