Efficient & Pythonic way of finding all possible sublists of a list in given range and the minimum product after multipying all elements in them?
我完成了这两件事。
查找给定范围
1 2 | A = [ 44, 55, 66, 77, 88, 99, 11, 22, 33 ] Let, i = 2 and j = 4 |
那么,给定范围内
1 | [66], [66,77], [66,77,88], [77], [77,88], [88] |
并且,在将子列表的所有元素多重化之后,生成的产品的最小值为:因此,将上述子列表中的所有元素相乘后的结果列表将变成
1 | X = [66, 5082, 447216, 77, 6776, 88]` |
现在,上述列表中的最小值是
我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | i, j = 2, 4 A = [ 44, 55, 66, 77, 88, 99, 11, 22, 33 ] O, P = i, i mini = A[O] while O <= j and P <= j: if O == P: mini = min(mini, reduce(lambda x, y: x * y, [A[O]])) else: mini = min(mini, reduce(lambda x, y: x * y, A[O:P + 1])) P += 1 if P > j: O += 1 P = O print(mini) |
我的问题:
对于较大的列表和较大的范围,执行此代码需要更多的时间!是否有任何可能的"Python式"方法来降低上述代码的时间复杂性?事先谢谢!
编辑:
知道了。但是,如果有多个子列表具有相同的最小产品,
如果是
尝试使用字典,它适用于某些输入,但不适用于所有输入!如何"有效地"做到这一点?谢谢您!
首先,给定列表和索引范围,就可以得到子列表
1 | [66, 77, 88] |
对于正整数
结果是:
1 | min(A[i : j + 1]) |
对于生成子列表,它与列表理解中的两个嵌套
1 2 | def sublists(l,i,j): return [l[m:n+1] for m in range(i,j+1) for n in range(m,j+1)] |
例子:
1 2 | >>> sublists(A,2,4) [[66], [66, 77], [66, 77, 88], [77], [77, 88], [88]] |
求最小积:
1 2 | >>> min(map(prod, sublists(A,2,4))) 66 |
(您从
接受的答案对于所有的正整数都是正确的,因为你不能用最小的元素乘以任何数字,得到的结果也会更小。如果所有切片的长度都大于1,这可能更有意义。
如果要计算它,那么可以使用
1 2 3 4 5 6 7 | from itertools import islice from operator import mul print(min(reduce(mul, islice(A, n, k + 1), 1) for n in range(i, j + 1) for k in range(n, j + 1))) 66 |
如果对于i=0和j=4,您认为
#编辑:快速解决方案:
1 | min(A[i:j+1]) |
因为所有的数字都是正整数,所以您需要找到
另一个解决方案:
当您需要找到子列表的最大乘积或需要
我们将使用itertools.combinations来解决这个问题。我们可以分三步完成。
步骤1:获取列表切片
1 | my_list = A[i:j+1] |
这将给我们一个工作机会。
1 2 3 | my_list = A[2:5] my_list [66, 77, 88] |
步骤2生成所有可能的组合:
1 2 3 4 5 6 7 8 9 | import itertools my_combinations = [] for x in range(1, len(my_list)+1): my_combinations.extend(list(itertools.combinations(my_list,x))) my_combinations [(66,), (77,), (88,), (66, 77), (66, 88), (77, 88), (66, 77, 88)] |
iterools.combinations returns r length subsequences of elements from
the input iterable
因此,我们将使用它生成长度为1到长度等于
步骤3:找到所有可能组合的最小积
1 2 3 4 5 | products_list = [reduce(lambda i,j:i*j, x) for x in my_combinations] [66, 77, 88, 5082, 5808, 6776, 447216] min(products_list) 66 |
在得到子序列后,我们将列表理解与
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def solution(a_list): sub = [[]] for i in range(len(a_list)): for j in range(len(a_list)): if(i == j): sub.append([a_list[i]]) elif(i > j): sub.append([a_list[j],a_list[i]]) sub.append(a_list) return sub solution([10, 20, 30]) |
1 | [[], [10], [10, 20], [20], [10, 30], [20, 30], [30], [10, 20, 30]] |
看一看
https://docs.python.org/3/library/itertools.html itertools.combinations.
在循环中调用它传递子列表,其他参数从1到子列表的长度不等。
我认为这肯定需要"为更大的列表和更大的范围执行更多的时间",这是不可避免的。但可能比你的方法快得多。测量并查看。