我正在阅读这篇文章,试图了解有关排列的更多信息:Finding all possible permutations of a given string in python
我对这段代码感到困惑:
def permutations(string, step = 0):
# if we've gotten to the end, print the permutation
if step == len(string):
print "".join(string)
# everything to the right of step has not been swapped yet
for i in range(step, len(string)):
# copy the string (store as array)
string_copy = [character for character in string]
# swap the current index with the step
string_copy[step], string_copy[i] = string_copy[i], string_copy[step]
# recurse on the portion of the string that has not been swapped yet (now it's index will begin with step + 1)
permutations(string_copy, step + 1)
我不理解我们将当前索引与步骤交换的行,这究竟是做什么的?我知道我们一旦向step
移动到右边,但string_copy[step], string_copy[i] = string_copy[i], string_copy[step]
如何帮助它?我不知道发生了什么
答案 0 :(得分:5)
a,b = b,a
是用于交换两个值的Python习语,也可以写成:
temp = a
a = b
b = temp
在for循环中,在排列(...)之上,添加以下行:
print "step", step, "index", i, string, "->", string_copy
现在它会在运行时显示内部工作原理:
>>> permutations("abc")
step 0 index 0 abc -> ['a', 'b', 'c']
step 1 index 1 ['a', 'b', 'c'] -> ['a', 'b', 'c']
step 2 index 2 ['a', 'b', 'c'] -> ['a', 'b', 'c']
abc
step 1 index 2 ['a', 'b', 'c'] -> ['a', 'c', 'b']
step 2 index 2 ['a', 'c', 'b'] -> ['a', 'c', 'b']
acb
step 0 index 1 abc -> ['b', 'a', 'c']
step 1 index 1 ['b', 'a', 'c'] -> ['b', 'a', 'c']
step 2 index 2 ['b', 'a', 'c'] -> ['b', 'a', 'c']
bac
step 1 index 2 ['b', 'a', 'c'] -> ['b', 'c', 'a']
step 2 index 2 ['b', 'c', 'a'] -> ['b', 'c', 'a']
bca
step 0 index 2 abc -> ['c', 'b', 'a']
step 1 index 1 ['c', 'b', 'a'] -> ['c', 'b', 'a']
step 2 index 2 ['c', 'b', 'a'] -> ['c', 'b', 'a']
cba
step 1 index 2 ['c', 'b', 'a'] -> ['c', 'a', 'b']
step 2 index 2 ['c', 'a', 'b'] -> ['c', 'a', 'b']
cab
我发现很难做出一个更加清晰的例子。怎么样:
# (step, index)
(0, 0) -- a
(1, 1) -- ab
(2, 2) -- abc # reached the last character, print this!
<-
(1, 2) -- ac
(2, 2) -- acb # reached the last character, print this!
<-
<-
(0, 1) -- b
(1, 1) -- ba
(2, 2) -- bac # reached the last character, print this!
<-
(1, 2) -- bc
(2, 2) -- bca # reached the last character, print this!
<-
<-
(0, 2) -- c
(1, 1) -- cb
(2, 2) -- cba # reached the last character, print this!
<-
(1, 2) -- ca
(2, 2) -- cab # reached the last character, print this!
<-
<-
-- a
下的所有内容,第二部分是-- b
下的所有内容,第三部分是-- c
下的所有内容。 --a
下的所有内容均以-- a
开头。 -- ab
下的所有内容均以-- ab
开头。并尝试回答您的评论问题:
行for i in range(step, len(string)):
从当前缩进/步骤级别启动索引计数器。这就是它在更深层次上从(1,1)到(2,2)的原因。你可以看到,当我们从(2,2)回来时,我们拿起之前的状态(1,1)并且在同一级别转到(1,2),然后转到(2) 2)在更深层次下。
我们从(2,2)回到(0,0)的原因是因为我们已经尽可能多次向右缩进到字符串的末尾,直到我们从'a'开始,用完了排列。 'abc'和'acb'然后我们回到开头,从'b'开始。 'bac'和'bca'。然后我们就跑了,回到开始。
e.g。
(0, 0) -- a
(1, 1) -- ab
(2, 2) -- abc #STEP has reached the end of the string, move left
# We moved left, index was 1 so we've got more work to do
(1, 2) -- ac
(2, 2) -- acb #STEP has reached the end of the string, move left
# We moved left, index was 2 so that has also reached the end of the string
# no more work to do inside the group (0,0) -- a, so move left again.
<-
# Now at this far left level, we can change the far left column from (0,0) to (0,1)
# and then repeat all of the above.
在每个级别,都会出现相同的模式。更改此列/级别,并重复所有较低级别。这是一种自相似的,递归的,循环的模式。
我的示例代码中有8个版本的print
语句,打印不同的事物组合以尝试显示正在发生的事情。我认为上面的内容是最明确的,但我鼓励你将print语句放入并重新运行。在交换之前和之后打印'string'和'string_copy',打印'string_copy [step:]'并打印" "*(3*(step+1))
以打印缩进。
我所知道的并不容易解释。没有什么可以替代盯着代码,一遍又一遍地处理它直到它更有意义。
答案 1 :(得分:1)
这是一段很好的代码。交换是在这里创建不同排列的步骤。 我试着用另外两个打印语句来运行它,如下所示:
def permutations(string, step = 0):
print string ############ADDED
if step == len(string):
print "".join(string)
# everything to the right of step has not been swapped yet
for i in range(step, len(string)):
string_copy = [character for character in string]
string_copy[step], string_copy[i] = string_copy[i], string_copy[step]
print step, i, string_copy ##############ADDED
permutations(string_copy, step + 1)
permutations("abc")
运行结果如下:
如果您观察到第一次传递返回'abc'本身作为步骤匹配我使交换琐碎。 然后交换b和c来创建acb,依此类推。