是否有可能在 O(1) 中获得 m 个字符长度组合的第 k 个元素?
Posted
技术标签:
【中文标题】是否有可能在 O(1) 中获得 m 个字符长度组合的第 k 个元素?【英文标题】:Is it possible to get k-th element of m-character-length combination in O(1)? 【发布时间】:2011-08-26 00:54:39 【问题描述】:你知道在 O(1) 中获得 m 元素组合的第 k 个元素的方法吗?预期的解决方案应该适用于任何大小的输入数据和任何 m 值。
让我通过例子来解释这个问题(python代码):
>>> import itertools
>>> data = ['a', 'b', 'c', 'd']
>>> k = 2
>>> m = 3
>>> result = [''.join(el) for el in itertools.combinations(data, m)]
>>> print result
['abc', 'abd', 'acd', 'bcd']
>>> print result[k-1]
abd
对于给定的 data,m 元素组合的第 k 个(本例中为第 2 个)元素是 abd。是否可以在不创建整个组合列表的情况下获得该值 (abd)?
我问是因为我有大约 1,000,000 个字符的数据,并且不可能创建完整的 m 字符长度组合列表来获取第 k 个元素。
解决方案可以是伪代码,也可以是描述此问题的页面链接(很遗憾,我没有找到)。
谢谢!
【问题讨论】:
为此,您需要明确定义的组合顺序。 【参考方案1】:http://en.wikipedia.org/wiki/Permutation#Numbering_permutations
基本上,在阶乘数字系统中表示索引,并将其数字用作原始序列中的选择(无需替换)。
【讨论】:
secure.wikimedia.org/wikipedia/en/wiki/… 这不是更有帮助吗? 是的。我是一个白痴。我把它读成排列,而不是组合。它们之间可能存在一个简单的映射,例如从一组 N 个唯一元素中提取的 k 个元素的第 j 个组合与 N 个元素的j(k!)((N-k!)
th 排列的前 k 个元素相同。但也许不是。【参考方案2】:
不一定是 O(1),但下面的应该很快:
取原来的组合算法:
def combinations(elems, m):
#The k-th element depends on what order you use for
#the combinations. Assuming it looks something like this...
if m == 0:
return [[]]
else:
combs = []
for e in elems:
combs += combinations(remove(e,elems), m-1)
对于n
初始元素和m
组合长度,我们有n!/(n-m)!m!
总组合。我们可以利用这个事实直接跳到我们想要的组合:
def kth_comb(elems, m, k):
#High level pseudo code
#Untested and probably full of errors
if m == 0:
return []
else:
combs_per_set = ncombs(len(elems) - 1, m-1)
i = k / combs_per_set
k = k % combs_per_set
x = elems[i]
return x + kth_comb(remove(x,elems), m-1, k)
【讨论】:
【参考方案3】:首先计算r = !n/(!m*!(n-m))
与n的元素数量
那么 floor(r/k) 是结果中第一个元素的索引,
删除它(将所有内容向左移动)
做 m--, n-- 和 k = r%k
并重复直到 m 为 0(提示 k 为 0 时只需将以下字符复制到结果中)
【讨论】:
【参考方案4】:我编写了一个类来处理处理二项式系数的常用函数,这是您的问题似乎属于的问题类型。它执行以下任务:
以适合任何 N 选择 K 的格式将所有 K 索引输出到文件。 K-indexes 可以替换为更具描述性的字符串或字母。这种方法使得解决这类问题变得非常简单。
将 K 索引转换为已排序二项式系数表中条目的正确索引。这种技术比依赖迭代的旧已发布技术快得多。它通过使用帕斯卡三角形固有的数学属性来做到这一点。我的论文谈到了这一点。我相信我是第一个发现并发表这种技术的人,但我可能是错的。
将已排序二项式系数表中的索引转换为相应的 K 索引。我相信它也比其他已发布的技术更快。
使用Mark Dominus 方法计算二项式系数,该方法不太可能溢出并且适用于较大的数字。
该类是用 .NET C# 编写的,并提供了一种通过使用通用列表来管理与问题相关的对象(如果有)的方法。此类的构造函数采用一个名为 InitTable 的 bool 值,当它为 true 时,将创建一个通用列表来保存要管理的对象。如果此值为 false,则不会创建表。无需创建表即可执行上述 4 种方法。提供访问器方法来访问表。
有一个关联的测试类显示如何使用该类及其方法。它已经过 2 个案例的广泛测试,没有已知的错误。
要了解该课程并下载代码,请参阅Tablizing The Binomial Coeffieicent。
将此类转换为 Java、Python 或 C++ 应该不难。
【讨论】:
以上是关于是否有可能在 O(1) 中获得 m 个字符长度组合的第 k 个元素?的主要内容,如果未能解决你的问题,请参考以下文章