【问题标题】:Given a list of elements in lexicographical order (i.e. ['a', 'b', 'c', 'd']), find the nth permutation - Average time to solve?给定一个按字典顺序排列的元素列表(即 ['a', 'b', 'c', 'd']),找到第 n 个排列 - 平均求解时间?
【发布时间】:2011-10-10 16:19:23
【问题描述】:

我偶然发现了这个面试问题:

给定一个按字典顺序排列的元素列表(即 ['a', 'b', 'c', 'd']),找到第 n 个排列

我自己试过了,我花了大约 30 分钟才解决。 (我最终在 Python 中得到了一个 ~8-9 行的解决方案)。只是好奇——解决这类问题需要多长时间?我用的时间太长了吗?

【问题讨论】:

标签: python list recursion combinations


【解决方案1】:

9 分钟,包括测试

import math

def nthperm(li, n):
    n -= 1
    s = len(li)
    res = []
    if math.factorial(s) <= n:
        return None
    for x in range(s-1,-1,-1):
        f = math.factorial(x)
        d = n / f
        n -= d * f
        res.append(li[d])
        del(li[d])
    return res

#now that's fast...
nthperm(range(40), 123456789012345678901234567890)

【讨论】:

  • 它从 1 开始(第一个排列),这就是 n -= 1&lt;= 的原因。顺便说一句,你的意思是math.factorial(len(li)),对吧?
  • 你能解释一下循环里面的部分吗? d = n/f n-= d*f
  • 如果你有一个像 [1,2,3,4] 这样的列表,那么最后 3 个元素有 3 个!排列,如果 n
  • 我希望有人指出销毁原始列表可能是个坏主意,但是哦,好吧..
  • 一开始做li=list(li) 可能更容易
【解决方案2】:

以防万一有人对当您查看“r-length-permutations”时可以找到“第 i 个”排列的解决方案感兴趣(由 itertools.permutationsr 参数表示):

from math import factorial

def ith_permutation(i, seq, r=None):
    li = list(seq)
    length = len(li)

    if r is None:
        r = length
    res = []
    current_factorial = factorial(length) // factorial(length - r)

    if current_factorial <= i:
        raise ValueError('out of range')

    for x in range(length, length-r, -1):
        current_factorial //= x
        div, mod = divmod(i, current_factorial)
        i = mod
        res.append(li[div])
        del(li[div])

    return res

例如:

>>> ith_permutationutation(10, [0, 1, 2, 3, 4], 2)
[2, 3]

>>> # correctness check:
>>> from itertools import permutations
>>> list(permutations([0, 1, 2, 3, 4], 2))[10]
(2, 3)

包括更完整的测试:

s = range(8)
for n in range(len(s)):
    for idx, item in enumerate(permutations(s, n)):
        assert list(item) == ith_permutation(idx, s, n)

这里使用了 Karoly Horvath 的部分答案。

【讨论】:

    【解决方案3】:

    也许我遗漏了什么,我想我们可以通过nth from itertools Recipespermutations 轻松找到它:

    from itertools import permutations, islice
    def nth(iterable, n, default=None):
        "Returns the nth item or a default value"
        return next(islice(iterable, n, None), default)
    def main():
        data = ['a', 'b', 'c', 'd']
        n = 7  # 0 indexed
        print nth(permutations(data), n)
    if __name__ == "__main__":
        main()
    

    【讨论】:

    • 如果 n 很大,它会非常慢,您必须生成 n 个排列并且只使用其中的 1 个。最初有一个完全一样的帖子,但随后 OP 解释说任务是在没有 itertools 帮助的情况下完成,然后海报将其删除。把它留在这里,对于小 n-s 来说这是一个完美的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2018-01-17
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-17
    相关资源
    最近更新 更多