文章目录
py3中 itertools 的常用STL
对于这个工具包其实使用起来还是有些吃力,现在对一些使用到的,较为常用的几个函数先做一个梳理:
主要包括:
accumulate() 函数,permutations() 函数,combinations() 函数,zip_longest() 函数。将结合一些LC上的例题进行一个简单总结。
参考文档链接为:https://docs.python.org/3.8/library/itertools.html?highlight=itertools
accumulate() 函数
accumulate() 函数是一个累加函数,举例:
accumulate([1,2,3,4,5]) ----> 1 3 6 10 15
举一个LC上的例题:
题目链接:813. 最大平均值和的分组(非常好的一道题)
题目大意:给定数组 nums 和一个整数 k 。我们将给定的数组 nums 分成 最多 k 个相邻的非空子数组 。 分数 由每个子数组内的平均值的总和构成。
注意我们必须使用 nums 数组中的每一个数进行分组,并且分数不一定需要是整数。
返回我们所能得到的最大 分数 是多少。答案误差在
1
0
−
6
10^{-6}
10−6 内被视为是正确的。
注意:(1)1 <= nums.length <= 100;(2)1 <= nums[i] <= 104;(3)1 <= k <= nums.length。
示例:
输入: nums = [9,1,2,3,9], k = 3
输出: 20.00000
解释:
nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 3 + 9 = 20.
我们也可以把 nums 分成[9, 1], [2], [3, 9].
这样的分组得到的分数为 5 + 2 + 6 = 13, 但不是最大值.
输入: nums = [1,2,3,4,5,6,7], k = 4
输出: 20.50000
参考代码:
class Solution:
def largestSumOfAverages(self, nums: List[int], k: int) -> float:
n = len(nums)
pref = list(accumulate(nums,initial=0))
dp = [[0.0]*(k+1) for _ in range(n+1)]
# print(dp)
for i in range(1,n+1):
dp[i][1] = pref[i]/i
# j 仅负责分的份数
for j in range(2,k+1):
# 记住 一共要分 j份 那么需要元素的最少个数为j
for i in range(j,n+1):
# x的选取 要在 j-1 到 i 个数字之间
for x in range(j-1,i):
dp[i][j] = max(dp[i][j],dp[x][j-1]+(pref[i]-pref[x])/(i-x))
return dp[n][k]
# 时间复杂度 O(K×N^2) K为分组数,N为数组的长度
# 空间复杂度 O(K×N)
permutations() 函数
一个穷尽组合的函数,举个函数示例:
permutations('ABC',2) ----> AB AC BA BC
举一个LC上的例题:
题目链接:949. 给定数字能组成的最大时间(含有很多知识点,非常综合的一道题,这里permutations()函数令代码非常简洁明了。)
题目大意:给定一个由 4 位数字组成的数组,返回可以设置的符合 24 小时制的最大时间。
24 小时格式为 “HH:MM” ,其中 HH 在 00 到 23 之间,MM 在 00 到 59 之间。最小的 24 小时制时间是 00:00 ,而最大的是 23:59 。从 00:00 (午夜)开始算起,过得越久,时间越大。
以长度为 5 的字符串,按 “HH:MM” 格式返回答案。如果不能确定有效时间,则返回空字符串。
注意:(1)arr.length == 4;(2)0 <= arr[i] <= 9。
示例:
输入:arr = [1,2,3,4]
输出:"23:41"
解释:有效的 24 小时制时间是 "12:34","12:43","13:24","13:42","14:23","14:32","21:34","21:43","23:14" 和 "23:41" 。这些时间中,"23:41" 是最大时间。
输入:arr = [5,5,5,5]
输出:""
解释:不存在有效的 24 小时制时间,因为 "55:55" 无效。
输入:arr = [0,0,0,0]
输出:"00:00"
输入:arr = [0,0,1,0]
输出:"10:00"
参考代码:
class Solution:
def largestTimeFromDigits(self, arr: List[int]) -> str:
ans = -1
for h1,h2,m1,m2 in itertools.permutations(arr):
hours = 10*h1+h2
mins = 10*m1+m2
time = hours*60 + mins
if 0<=hours<24 and 0<=mins<60 and time>ans:
ans = time
# 函数前 单星号 将所有参数以元组(tuple)形式导入; 双星号 字典形式导入
# print(*divmod(ans,10))
return "{:02}:{:02}".format(*divmod(ans,60)) if ans>=0 else ""
# 时间复杂度 O(1)
# 空间复杂度 O(1)
**chain()**函数(23.2.28补充)
一个连接两个列表的迭代器,挺好用的,以前怎么没发现。
chain('ABC', 'DEF') --> A B C D E F
举一个LC上的例题:
题目链接:2363. 合并相似的物品
题目大意:给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数组 items 有以下特质:
items[i] =
[
v
a
l
u
e
i
,
w
e
i
g
h
t
i
]
[value_i, weight_i]
[valuei,weighti] 其中
v
a
l
u
e
i
value_i
valuei 表示第 i 件物品的 价值 ,
w
e
i
g
h
t
i
weight_i
weighti 表示第 i 件物品的 重量 。
items 中每件物品的价值都是 唯一的 。
请你返回一个二维数组 ret,其中 ret[i] =
[
v
a
l
u
e
i
,
w
e
i
g
h
t
i
]
[value_i, weight_i]
[valuei,weighti],
w
e
i
g
h
t
i
weight_i
weighti 是所有价值为
v
a
l
u
e
i
value_i
valuei 物品的 重量之和 。
注意:ret 应该按价值 升序 排序后返回。
注意:(1)1 <= items1.length, items2.length <= 1000;(2)items1[i].length == items2[i].length == 2;(3)1 <= v a l u e i , w e i g h t i value_i, weight_i valuei,weighti <= 1000;(4)items1 中每个 v a l u e i value_i valuei 都是 唯一的 ,items2 中每个 v a l u e i value_i valuei 都是 唯一的 。
示例:
输入:items1 = [[1,1],[4,5],[3,8]], items2 = [[3,1],[1,5]]
输出:[[1,6],[3,9],[4,5]]
解释:
value = 1 的物品在 items1 中 weight = 1 ,在 items2 中 weight = 5 ,总重量为 1 + 5 = 6 。
value = 3 的物品再 items1 中 weight = 8 ,在 items2 中 weight = 1 ,总重量为 8 + 1 = 9 。
value = 4 的物品在 items1 中 weight = 5 ,总重量为 5 。
所以,我们返回 [[1,6],[3,9],[4,5]] 。
输入:items1 = [[1,1],[3,2],[2,3]], items2 = [[2,1],[3,2],[1,3]]
输出:[[1,4],[2,4],[3,4]]
解释:
value = 1 的物品在 items1 中 weight = 1 ,在 items2 中 weight = 3 ,总重量为 1 + 3 = 4 。
value = 2 的物品在 items1 中 weight = 3 ,在 items2 中 weight = 1 ,总重量为 3 + 1 = 4 。
value = 3 的物品在 items1 中 weight = 2 ,在 items2 中 weight = 2 ,总重量为 2 + 2 = 4 。
所以,我们返回 [[1,4],[2,4],[3,4]] 。
输入:items1 = [[1,3],[2,2]], items2 = [[7,1],[2,2],[1,4]]
输出:[[1,7],[2,4],[7,1]]
解释:
value = 1 的物品在 items1 中 weight = 3 ,在 items2 中 weight = 4 ,总重量为 3 + 4 = 7 。
value = 2 的物品在 items1 中 weight = 2 ,在 items2 中 weight = 2 ,总重量为 2 + 2 = 4 。
value = 7 的物品在 items2 中 weight = 1 ,总重量为 1 。
所以,我们返回 [[1,7],[2,4],[7,1]] 。
参考代码(参考LC大佬的代码):
class Solution:
def mergeSimilarItems(self, items1: List[List[int]], items2: List[List[int]]) -> List[List[int]]:
cnt = Counter()
for v, w in chain(items1, items2):
cnt[v] += w
return sorted(cnt.items())
# 时间复杂度 O(n+m),n和m分别为items1和items2的长度
# 空间复杂度 O(n+m)
**product()**函数(23.3.1、3.7补充)
一个连续组合输出的迭代器,挺好用的。
product('ABCD', repeat=2) ----->
AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD
举一个LC上的例题:
题目链接:318. 最大单词长度乘积
题目大意:给你一个字符串数组 words ,找出并返回 length(words[i]) * length(words[j]) 的最大值,并且这两个单词不含有公共字母。如果不存在这样的两个单词,返回 0 。
注意:(1)2 <= words.length <= 1000;(2)1 <= words[i].length <= 1000;(3)words[i] 仅包含小写字母。
示例:
输入:words = ["abcw","baz","foo","bar","xtfn","abcdef"]
输出:16
解释:这两个单词为 "abcw", "xtfn"。
输入:words = ["a","ab","abc","d","cd","bcd","abcd"]
输出:4
解释:这两个单词为 "ab", "cd"。
输入:words = ["a","aa","aaa","aaaa"]
输出:0
解释:不存在这样的两个单词。
参考代码:
class Solution:
def maxProduct(self, words: List[str]) -> int:
ms = defaultdict(int)
for word in words:
m = reduce(lambda a, b: a | (1 << (ord(b) - ord('a'))), word, 0)
ms[m] = max(ms[m], len(word))
return max([ms[x] * ms[y] for x, y in product(ms,repeat=2) if x&y==0] or [0])
# 时间复杂度 O(L+n^2),L为words中全部单词的长度之和,n为数组words的长度
# 空间复杂度 O(n)
- 再添加一道很不错的例题,与字符串有关。
题目链接:17. 电话号码的字母组合
题目大意:给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
注意:(1)0 <= digits.length <= 4;(2)digits[i] 是范围 [‘2’, ‘9’] 的一个数字。
示例:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
输入:digits = ""
输出:[]
输入:digits = "2"
输出:["a","b","c"]
参考代码:
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
if len(digits)==0:return []
d = {"2":"abc","3":"def","4":"ghi","5":"jkl","6":"mno",\
"7":"pqrs","8":"tuv","9":"wxyz"}
# 方法一:
g = [d[digit] for digit in digits]
# print(g,*g) *g 代表去掉g最外侧的中括号
return ["".join(com) for com in itertools.product(*g,repeat=1)]
# 复杂度应该和使用递归的差不多
# 时间复杂度 O(3^m+4^n),m,n分别为输入含有3个或4个字符的数字个数
# 空间复杂度 O(m+n)
combinations() 函数(缺例题)
另一种一个按顺序穷尽组合的函数,举个函数示例:
combinations('ABC',2) ----> AB AC BC
举一个LC上的例题:
题目链接:
题目大意:
注意:
示例:
参考代码:
在这里插入代码片
zip_longest() 函数(缺例题)
和zip()函数的功能一致,zip()函数只能处理同样长度的子串组合,而zip_longest()函数可以处理不同长度的子串组合,例如:
zip_longest('ABCD','xy',fillvalue='-') ----> Ax By C- D-
举一个LC上的例题:
题目链接:
题目大意:
注意:
示例:
参考代码:
在这里插入代码片
小结
时间不等人,抓紧时间学习吧。