关于递归:在递归调用python中交换list的元素

swap elements of list in recursive call python

我想让简单的函数交换列表中的随机元素。但在递归调用中不起作用。

在第一个递归调用中,元素交换工作,但是嵌套递归调用(或第一个递归调用中的嵌套递归调用)不起作用。

我不知道为什么在第一个递归调用中只交换有效。

以下是结果。

谢谢大家。

1
2
3
4
5
6
7
8
9
10
11
12
def change(lst):
    if len(lst)>4:
        a, b = np.random.randint(0, len(lst)), np.random.randint(0, len(lst))
        print(lst)
        lst[a], lst[b] = lst[b], lst[a]
        print(lst)
        mid = int(len(lst)/2)
        change(lst[:mid])
        change(lst[mid:])
k = list(range(0, 20))
change(k)
print(k)

`

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[0, 19, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1]
[0, 19, 2, 3, 4, 5, 6, 7, 8, 9]
[3, 19, 2, 0, 4, 5, 6, 7, 8, 9]
[3, 19, 2, 0, 4]
[3, 0, 2, 19, 4]
[5, 6, 7, 8, 9]
[5, 6, 8, 7, 9]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 1]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 1]
[10, 11, 12, 13, 14]
[10, 14, 12, 13, 11]
[15, 16, 17, 18, 1]
[15, 16, 17, 18, 1]
[0, 19, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1] <= result.


问题在于,在递归调用中:

1
2
change(lst[:mid])
change(lst[mid:])

您使用切片运算符。切片运算符构造一个新列表,因此您的更改将在新列表上进行,而不会反映在原始列表上(因为它是一个副本)。

您可以使用索引代替:

1
2
3
4
5
6
7
8
9
10
11
def change(lst,frm=0,to=None):
    if to is None: # set the default to the end of the list
        to = len(lst)
    if to-frm > 4:
        a, b = np.random.randint(frm,to), np.random.randint(frm,to)
        print(lst)
        lst[a], lst[b] = lst[b], lst[a]
        print(lst)
        mid = (frm+to)//2
        change(lst,frm,mid)
        change(lst,mid,to)

然后我们得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> k = list(range(0, 20))
>>> change(k)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 2, 3, 4, 12, 6, 7, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 2, 3, 4, 12, 6, 7, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 2, 3, 4, 12, 6, 7, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 2, 3, 4, 12, 6, 7, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 12, 6, 7, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 12, 6, 7, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 7, 6, 12, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 7, 6, 12, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 7, 6, 12, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 7, 6, 12, 8, 9, 10, 11, 5, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 7, 6, 12, 8, 9, 5, 11, 10, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 7, 6, 12, 8, 9, 5, 11, 10, 13, 14, 15, 16, 17, 18, 19]
[0, 1, 4, 3, 2, 7, 6, 12, 8, 9, 5, 11, 10, 13, 14, 15, 16, 17, 18, 19]
>>> print(k)
[0, 1, 4, 3, 2, 7, 6, 12, 8, 9, 5, 11, 10, 13, 14, 15, 16, 17, 18, 19]


这是因为您创建了lst[:mid]lst[mid:]的原始列表的副本。解决方案是将同一列表和(单独)要处理的范围传递给change()