全排列就是,给定一个序列,列举出该序列中元素所有的排列情况,列举方法有递归和非递归两种,详细可以见这位大神写的博客:https://blog.csdn.net/jopus/article/details/18998403。我只列出来两个重要的图吧。
1.非递归:字典序法 ,如下图[1,2,3]的例子
2.递归方法
递归方法就是将序列中第一位固定,然后将后面n-1为的全排列列举出来,取遍第一位所有取值,递归地得到所有排列。
python实现如下:
# -*- coding:utf-8 -*-
# _author_ = xu_qn
# 全排列 分为两种:递归与非递归
# 递归方法
def recursion_permutation(list, first, last):
if first >= last: # 递归结束情况
print(list)
for i in range(first, last): # first包含,last不包含
list[i], list[first] = list[first], list[i]
recursion_permutation(list, first+1, last)
list[i], list[first] = list[first], list[i] # 交换回来,还原成原来的序列放置重复交换
# 非递归:字典序法
def is_not_reverse(list): # 判断是否为倒叙list
for i in range(len(list)-1):
if list[i] < list[i+1]:
return True
return False
def find_first_min(list): # 从右到左是递增的 只需要找到最右大于pi的数
for i in range(len(list)-1, 0, -1):
if list[i] > list[0]:
min_index = i
break
return min_index
def reverse_list(list,first,last):
while first < last:
if list[first] > list[last]:
list[first], list[last] = list[last], list[first]
first += 1
last -= 1
def dictionary_permutation(list):
while is_not_reverse(list):
for i in range(len(list) - 2, -1, -1):
if list[i] < list[i + 1]: # 从左到右找到第一个左边小于右边的数pi 坐标i
j = find_first_min(list[i:]) # 找到pi右边数字中比pi大的最小数下标
list[i], list[j+i] = list[j+i], list[i] # 交换pi,pj,pj在原list的坐标i+j
reverse_list(list, i+1, len(list)-1) # 将pi后的list倒转,变为升序
print(list)
if __name__ == "__main__":
list = [1, 2, 3, 4, 5]
#recursion_permutation(list, 0, len(list))
dictionary_permutation(list)