python set速度优于list
leetcode 523 连续的子数组和
做这道题的时候发现用list做超时了,用set做速度很快。
一、速度对比
1.1 上网查了下list和set的速度,下面是别人的对比
python的列表(list)和集合(set)速度对比,set速度惊人
1.2 list、set的构造
>>> l = [x for x in range(0,1000)]
>>> r = {x for x in range(0,1000)}
>>> type(l)
<class 'list'>
>>> type(r)
<class 'set'>
1.3 比较
循环速度: list最适合做固定长度的遍历,而且有顺序。所以这种循环尽量用list
查询速度: set > list, set查询的key都是hash过的,所以速度最快,list不适合用来做查询
增删速度: set > list, list的append操作尽量少做,因为会涉及重新分配地址的问题,set只需要增长指针链表
空间上: 由于list默认预留的空间会随着append指数级的变大,所以空间上也是set。
二、题目思路
给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:
子数组大小 至少为 2 ,且
子数组元素总和为 k 的倍数。
如果存在,返回 true ;否则,返回 false 。
如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 x 是 k 的一个倍数。0 始终视为 k 的一个倍数。
输入:nums = [23,2,4,6,7], k = 6
输出:true
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6 。
思路:对每个位置的nums[i]求nums[:i]的和,相减可以得到k的倍数的就满足。但是这样做每次都要跟前面0到i-2的和相减。而如果sum(nums[p:q])的和是k的倍数,
那么
s
u
m
(
n
u
m
s
[
0
:
p
]
)
sum(nums[0:p])%k=sum(num[0:q])%k
sum(nums[0:p])是成立的。
那么可以记录每个位置的和除以k的余数,如果前面有出现,则满足条件。
class Solution:
def checkSubarraySum(self, nums: List[int], k: int) -> bool:
left = set()
left.add(0)
presum = nums[0] % k
for i in range(1, len(nums)):
cursum = (presum + nums[i]) % k
if cursum in left:
return True
left.add(presum)
presum = cursum
return False