我想让项目Euler 24的解决方案更有效率

时间:2016-05-11 20:37:04

标签: python algorithm permutation

我在1分32秒内解决了这个问题。我的解决方案如下。有没有更好的方法来解决它?

def fill_in(letter, word):
    perm = []
    for i in xrange(len(word)+1):
        the_word = word[0:i] + letter + word[i:]
        if the_word[0] == '2':
            perm.append(the_word)
    return perm

def perm(string):
    "Find all permutations of given string"
    perm_list = []
    for i in string:
        if len(perm_list) == 0:
            perm_list.append(i)
        else:
            temp = []
            while (len(perm_list) != 0):
                temp = temp + fill_in (i, perm_list.pop())
            perm_list = temp
    return perm_list





j = perm("2013456789")
j.sort()
print j[1000000-725760-1]

3 个答案:

答案 0 :(得分:2)

对于您当前的算法,可以做的不多。 itertools.permutations函数会为你做的大部分事情做得更快,但这并不好玩。问题的关键在于,通过聪明的数学,你可以找出答案,而不会产生所有的排列。有关此问题的示例讨论,请访问:http://www.mathblog.dk/project-euler-24-millionth-lexicographic-permutation/

答案 1 :(得分:2)

这是一个简单的代码,可以立即提供答案:

from math import factorial

digits = range(10)
res = []
n = 999999 # PE uses 1-based indexing

for i in xrange(len(digits) - 1, -1, -1):
    index, n = divmod(n, factorial(i))
    res.append(digits.pop(index))

print ''.join(str(i) for i in res)

它基于阶乘,原理非常简单。假设您有数字1234,结果为4!个排列。 3!第一个排列以1开头,因此您只需将排列数除以3!即可得到第一个数字的索引。然后从可用数字中删除数字并将其添加到结果中。对于以下数字,使用前一个除法的余数作为置换数。

答案 2 :(得分:0)

def permutation(order):
    start = time.time()
    digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  # our main list.
    original_digits = digits.copy()  # take a shallow copy of the list.
    i = 1
    result = 0
    wanted_num = ""
    while i <= len(original_digits):
        x = 0
        while True:
            # removing the number of redundant possibilities.
            result += factorial(len(original_digits) - i)
            x += 1
            if result > order - 1:
                result -= factorial(len(original_digits) - i)
                x -= 1
                wanted_num += str(digits[x])
                digits.remove(digits[x])  # prevent repetition.
                break
        i += 1
        if result == order and len(digits) == 0:
            break
    return int(wanted_num), time.time() - start

使用以下行对其进行测试:

print(permutation(1000000))