用于查找没有特定列表Python长度的“有序组合”的数量的函数

问题描述 投票:0回答:3

尽管此问题的变体在此站点上已被问过很多次,但我还没有找到有关如何对给定列表进行“有序组合”的任何信息。

首先,我不完全知道此函数的正确术语是什么,但是我将使用此列表:

list = [1,2,3,4,5,6,7,8,9,10]

我想找到的是此列表可以有多少种排序方式,所以

list[0] < list[1] < list[2] ... < list[len(list)-1](升序不重复)

但是

[list[0] + 1不必等于list[1](选择哪个数字无关紧要,只要它们按升序排列并在列表中)]

并且,假设outList是源自list的合格列表

[len(outList)不一定要与len(list)相同-“合格”列表的长度不必与给定列表的长度相同,但不得更长。

一些符合这些规则的示例:

[1,4,5,9][2,6,7,8,9][1,2,4,8][8,10]

一些非示例:

[1,3,2,5,10][1,1,10][5,2,8,7,9]

数字不能重复,并且必须严格大于前一个数字。

我将如何实现这种功能?我对如何解决这个问题一无所知。我尝试使用for循环,但似乎无法正常工作。

编辑:对不起,这个问题尚不清楚,如果仍然存在,因为我真的不知道该使用什么术语。我不知道如何正确地表达它,因此我添加了更多细节,下面是我的答案版本。显然,它没有优化。顺便说一句,AlexanderCécile,如果您查看我的历史,我曾经使用过js和jQuery(不是我不再使用了,但是我改变了方向),因此该函数遵循js的命名标准。

第二编辑:所有这些答案彼此都大相径庭,这表明了编码的美:)-尽管我的解决方案确实有效,但我的解决方案是非常基本的。这些命令在长度较大的列表(例如[1,2,3,4 ... 100,101])上运行更快吗?

python python-3.x permutation
3个回答
1
投票

您可以使用formula to calculate the number of combinations进行数学计算。

import math
def binomial_coeff(n, k):
    return math.factorial(n) // (math.factorial(k) * math.factorial(n - k))

def num_all_combinations(lst_len):
    return sum(binomial_coeff(lst_len, i) for i in range(lst_len))

list1 = list(range(10))
print(num_all_combinations(len(list1))) # prints 1023

binomial_coeff函数使用组合公式(也称为二项式系数)来获取大小为n且组大小为k的列表的组合数量。然后,我们使用num_all_combinations函数来获取所有组大小的组合数,并将它们加在一起。

您甚至可以使用@ kaya3建议的sums of binomial coefficients identity进一步简化此操作。这将导致以下代码:

list1 = list(range(10))
print(2**len(list1) - 1) # prints 1023

1
投票

据我所知,您想知道有多少个不同的列表,其中某些元素的子集为lst,并保持顺序。因为每个子集只能以一种顺序存在,所以答案就是number of subsets:2 ^ n,其中n是列表的长度。

def count_subsets(lst):
    return 2 ** len(lst)

例如,如果列表为[1, 2, 3],则有2 ^ 3 = 8个有序子列表:

  1. []
  2. [1]
  3. [2]
  4. [3]
  5. [1, 2]
  6. [1, 3]
  7. [2, 3]
  8. [1, 2, 3]

如果要排除空白列表和/或原始列表,则可以根据需要简单地执行2 ** len(lst) - 1max(0, 2 ** len(lst) - 2)。当输入列表为空时,max(0, ...)处理特殊情况。


以上处理输入列表的元素完全不同时的情况,如您的示例。如果可能有重复的元素,则上面的公式会计数过多。为了解决这个问题,我们可以使用Counter查找每个元素的副本数。如果某个元素有k个副本,则应该计算2 ** k个包含0、1、2,...,k个副本的子列表,而不是k + 1组合。

from collections import Counter

def count_subsets(lst):
    r = 1
    for k in Counter(lst).values():
        r *= k + 1
    return r

0
投票

此解决方案很可能尚未优化,但我以某种方式想出了我想做的事情。有什么好方法可以改善这一点吗?


0
投票

这似乎符合您的要求:

© www.soinside.com 2019 - 2024. All rights reserved.