py3中 itertools 的常用STL

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} 106 内被视为是正确的。

注意:(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上的例题:
题目链接:
题目大意:
注意:
示例:
参考代码:

在这里插入代码片

小结

 时间不等人,抓紧时间学习吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值