給定一個無重複整數數組,返回所有可能的排列。
示例:
Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路
1、字典序法
使用字典序法不斷尋找當前排序的下一個排序,直至返回到了起始序列。
2、深度優先搜索
使用遞歸法,維護一個結果數組、以及每個元素對應的剩餘元素集合。每次依次從剩餘的元素集合中取出一個,並且分別追加到每一個已取序列的最後,直至剩餘元素集合爲空。
3、廣度優先搜索
維護一個狀態列表,裏面的元素是所有狀態詞典,詞典中有兩個key,記錄已經搜索到的和尚未搜索到的。
每次循環,對於所有狀態詞典,對每個尚未搜索到的數字,都拼接到已經搜索到的數組的末尾,然後形成一個新的狀態列表。
這樣,每次循環,所有狀態詞典中的已搜索到的序列長度+1,尚未搜索到的集合長度-1。
因此,只需要循環 len(nums) 次,所有狀態都表示搜索完畢了。
4、分治法
設nums的長度爲n,則前n項的全排列 = 第n個數字依次插入到前n-1項的全排列的兩兩之間的縫隙中(包括首尾兩端)。
因此可以使用遞歸。
python實現
import copy
def permute(nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
字典序法。
"""
def nextPermutation(nums):
"""
:type nums: List[int]
尋找下一個字典序排列
"""
l = len(nums)
result = copy.deepcopy(nums)
# 從右向左查詢第一個小於右鄰的元素
for i in range(l-2, -1, -1):
if result[i+1] > result[i]:
break
else: # 沒有找到,說明爲降序排列
result[:] = result[::-1]
return result
# 從右向左查詢第一個大於nums[i]的元素
for j in range(l-1, -1, -1):
if result[j] > result[i]:
break
# 交換i和j
result[i], result[j] = result[j], result[i]
# i後面的序列進行反轉
result[i+1:l] = result[-1:i:-1]
return result
if not nums:
return []
result = [nums]
cur = nums
while(True):
cur = nextPermutation(cur)
if cur == nums: # 回到了第一個
break
result.append(cur)
return result
def permute2(nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
深度優先搜索。
"""
def get_rest(result_list, pre_list, rest_set):
'''
遞歸,對rest_set進行全排列,並分別與pre_list拼接,最終加入到result_list中
'''
if not rest_set:
result_list.extend(pre_list)
for i in rest_set:
get_rest(result_list, [x+[i] for x in pre_list], rest_set-{i})
result_list = []
get_rest(result_list, [[]], set(nums))
return result_list
def permute3(nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
廣度優先搜索。
"""
state_list = [{'pre':[],'rest':set(nums)}]
for _ in range(len(nums)): # 循環len(nums)次
new_state_list = []
for dic in state_list:
for num in dic['rest']:
new_state_list.append({'pre':dic['pre']+[num],'rest':dic['rest']-{num}})
state_list = new_state_list
return [x['pre'] for x in state_list]
def permute4(nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
分治法。
"""
def get_permutes(n):
'''
得到nums前n項的全排列。
'''
# 遞歸結束條件
if n == 1:
return [[nums[0]]]
# 得到前n-1項的全排列
pre_list = get_permutes(n-1)
# 將第 n 個元素,依次插入到 pre_list 中的元素縫隙中
result_list = []
for permute in pre_list:
for i in range(len(permute)+1):
result_list.append(permute[:i] + [nums[n-1]] + permute[i:])
return result_list
return get_permutes(len(nums))
if '__main__' == __name__:
nums = [1,2,3]
print(permute4(nums))