编写一个程序来显示“的所有字谜”;abcdef“;用Python

编写一个程序来显示“的所有字谜”;abcdef“;用Python,python,anagram,Python,Anagram,我的朋友编写了一段代码,用python显示“abcdef”的所有字谜。但是在这段代码中,我无法理解递归过程是如何工作的anagrams=get\u list\u of\u anagrams('''.join(tmp\u list))函数如何调用自身 def get_list_of_anagrams(s): if len(s)==0: return [''] all_chars = list(s) unique_chars = list(set(s))

我的朋友编写了一段代码,用python显示“abcdef”的所有字谜。但是在这段代码中,我无法理解递归过程是如何工作的
anagrams=get\u list\u of\u anagrams('''.join(tmp\u list))
函数如何调用自身

def get_list_of_anagrams(s):
    if len(s)==0:
        return ['']
    all_chars = list(s)
    unique_chars = list(set(s))
    anagrams_list = []
    for char in unique_chars:
        tmp_list = list(all_chars)
        tmp_list.remove(char)
        anagrams = get_list_of_anagrams(''.join(tmp_list))
        for i in range(len(anagrams)):
            anagrams[i] = char+anagrams[i]
        anagrams_list += anagrams
    return anagrams_list
当我试着打印每件事直到
anagrams=get\u list\u of\u anagrams(''.join(tmp\u list)

我把下面的东西拿出来

对于以下代码:

def get_list_of_anagrams(s):
    if len(s)==0:
        return ['']
    all_chars = list(s)
    unique_chars = list(set(s))
    anagrams_list = []
    for char in unique_chars:
        tmp_list = list(all_chars)
        tmp_list.remove(char)
        anagrams = get_list_of_anagrams(''.join(tmp_list))
        print anagrams
        for i in range(len(anagrams)):
            anagrams[i] = char+anagrams[i]
        anagrams_list += anagrams
    return anagrams_list  

print get_list_of_anagrams('abc')
我得到以下输出:

有人能解释一下为什么上面的输出是这种模式吗?

这是一个递归函数。 例如著名的斐波那契序列:

def fib(n):
    if n < 2:
        return n
    return fib(n-2) + fib(n-1)
print fib(10)
def fib(n):
如果n<2:
返回n
返回fib(n-2)+fib(n-1)
打印fib(10)
查看更多信息。

通过以下方式跟踪:

def get_list_of_anagrams(s):
    # base case - empty string, return empty
    if len(s)==0:
        return ['']

    # figure out which characters are available
    all_chars    = list(s)       # may have repeats
    unique_chars = list(set(s))  # no repeats

    # prepare to store all results
    anagrams_list = []

    # for each unique character
    for char in unique_chars:
        # remaining unused characters
        tmp_list = list(all_chars)
        tmp_list.remove(char)

        # recurse: get all anagrams of remaining characters
        anagrams = get_list_of_anagrams(''.join(tmp_list))

        # prefix each result with picked character
        for i in range(len(anagrams)):
            anagrams[i] = char+anagrams[i]

        # add to overall results
        anagrams_list += anagrams

    # return all results
    return anagrams_list
我会重写一下,就像

def get_list_of_anagrams(s):
    anagrams = []

    remaining = list(s)
    for char in sorted(set(s)):
        remaining.remove(char)
        if remaining:
            # recurse: get all anagrams of remaining characters
            for anagram in get_list_of_anagrams(remaining):
                # prefix each result with picked character
                anagrams.append(char + anagram)
        else:
            anagrams.append(char)
        remaining.append(char)

    # return all results
    return anagrams
因此,要查找
get\u-list\u-of-anagrams(“abcdef”)
,您需要

"a" + each(get_list_of_anagrams("bcdef"))
"b" + each(get_list_of_anagrams("acdef"))
"c" + each(get_list_of_anagrams("abdef"))
"d" + each(get_list_of_anagrams("abcef"))
"e" + each(get_list_of_anagrams("abcdf"))
"f" + each(get_list_of_anagrams("abcde"))

等等。

这个想法是,要找到
'abc'
的字谜,首先要找到
'bc'
的所有字谜,首先要找到
'c'
的所有字谜,首先要找到
'
的所有字谜

那么,给定“内层”的所有字谜,你如何找到“外层”的字谜呢?给定
'bc'
的所有字谜(它们是
'bc'
'cb'
),您可以通过将
a
插入
'bc'
'cb'
的每个位置来查找
'abc'
的所有字谜。详细信息:

# 'bc' will give these anagrams:
abc # insert 'a' at first position
bac # insert 'a' at second position
bca # insert 'a' at third position (also last)

# Similarly, 'cb' gives:
acb
cab
cba
因此,2个
'bc'
的字谜给你6个
'abc'
的字谜

===


关于您的算法:它在每次递归时删除1个字符(使用
tmp_list.remove(char)
)。在
len=0的基本情况下(即当所有字符都已删除时),它只返回
'
。然后使用上述逻辑继续查找
'f'
的字谜,然后查找
'ef'
…的字谜,最后返回
abcdef

的字谜

import itertools
d = 'abc'
e = len(d)
j = list()

for p in itertools.permutations(d, e):
    print p

('a', 'b', 'c')
('a', 'c', 'b')
('b', 'a', 'c')
('b', 'c', 'a')
('c', 'a', 'b')
('c', 'b', 'a')

我知道这是一个递归函数。但我不明白它是如何在这种情况下应用的。我试图更改链接,使其成为一个真正的递归定义;-)在你的函数中,你会得到一个空列表,因为与你的朋友编写的
return['']
相比,它只
return[']
返回字谜列表
。要理解递归函数,请尝试找到退出(返回
并从那里跟踪
范围内的i(len(anagrams)):
但len(anagrams)不是空的吗。因为当我打印字谜时,我会得到一个空列表。那么为什么我的朋友在len(anagrams)上循环的代码是空的呢?把这个命令
print anagrams
放在
anagrams=get\u list\u of anagrams('''.join(tmp\u list))
后面。它将向您展示如何递归works@whale_steward好的,我试试这个one@whale_steward-我试过你的建议。但每次迭代之后,我都会得到一个空列表[“”],然后是一个单词。在这个场景中,递归是如何实现的,我对此感到困惑。除了递归部分,我什么都懂。例如,斐波那契解释了递归()。这个问题中的递归函数也有类似的逻辑吗?您的解决方案非常好:)。是否可以不使用递归编写此函数。我知道这是离题的,但如果您能帮助我,这将是非常棒的。我认为它可以作为一个迭代算法编写-Knuth的置换算法稍加修改,以防止相同的字母重复(即“abcb”只应返回一次)。事实上,Knuth可能包括了这个,你必须检查一下。基本上,它涉及到根据一组规则重复地重新排列字母列表,例如参见
itertools.permutations
的源代码。它比递归解决方案快一点(但也很难理解)。好的,我肯定会看一下itertools.permutations。每次迭代后,我都会得到一个空列表[“”],然后是一个单词。在这个场景中,递归是如何实现的,我对此感到困惑。你能给我解释一下吗?嗨,Huy,我已经更新了问题。通过你的解释,我能百分之五十地听懂你的解释。但我不明白为什么我会有这样的模式。
import itertools
d = 'abc'
e = len(d)
j = list()

for p in itertools.permutations(d, e):
    print p

('a', 'b', 'c')
('a', 'c', 'b')
('b', 'a', 'c')
('b', 'c', 'a')
('c', 'a', 'b')
('c', 'b', 'a')