列表元素的所有排列

列表元素的所有排列

  case:有乱序、不定长列表如[1,3,5,2],打印所有列表元素所有排列情况,并计数

 

  思路:重复的步骤--》长度为n的排列-》长为n-1的排列,长为n-2的排列

  .........

  直到长度为1,只有一个元素,输入当前的排列顺序

 

n = [1,2,3,4]
res = []
count = 0

def func1(k,start,end):
    global count
    if end == start:
        count += 1
        print(k)
        # res.append(k[:])
        return
    for i in range(start,end+1): #循环列表,从列表中选取一个元素作为排列的首元素,将剩余n-1的序列传入子递归函数
        k[start],k[i] = k[i],k[start] 
        
        func1(k,start+1,end)
        k[start],k[i] = k[i],k[start] # 将替换后的序列重置为原来的序列,确保后续循环中,选出的首元素是没选择过的元素
  # 递归层数从上往下(由外到内)的过程中对列表进行新的排列,
  # 由内到外的过程中将列表重置为每层递归函数传入列表的时的排序方式
func1(n,0,len(n)
-1) print(count)

  升级:将所有排列结果放在一个大列表中

n = [1,2,3,4]
res = []
count = 0

def func1(k,start,end):
    global count
    if end == start:
        count += 1
        print(k)
        res.append(k[:])
        return
    for i in range(start,end+1):
        k[start],k[i] = k[i],k[start]
        
        func1(k,start+1,end)
        k[start],k[i] = k[i],k[start]

func1(n,0,len(n)-1)
print(count)

  解释:为什么res.append(k[:])而不是res.append(k)?

  所有递归层数中操作的同一个对象(对象的不同引用),

  res.append(k)以后,最终的列表中子元素列表k都指向同一个对象

  第一句k[start],k[i] = k[i],k[start] 对列表k重新排序之后

  第二句k[start],k[i] = k[i],k[start] 将列表重置为原来的排序方式,最终结果res大列表中,所有子元素列表都指向同一个对象(新排序然后又重置为原来排序方式的列表)

  所以要用切片(浅copy)copy出值相同对象(值相等,但是是两个列表对象)

  深浅copy(对象与引用)请参照我的另一篇文章

  https://www.cnblogs.com/rain-chenwei/p/10222990.html


 

posted @ 2019-01-04 23:57  dmyHero  阅读(760)  评论(0编辑  收藏  举报