序號 | 文獻 |
---|---|
1 | 全排列算法part1 |
2 | 全排列算法part2 |
3 | 全排列算法的全面解析 |
4 | 一次搞懂全排列——LeetCode四道Permutations問題詳解 |
在LeetCode中一共有4個和全排列相關的題目分別是:算法
題號 | 題目 |
---|---|
31 | Next Permutation |
46 | Permutations |
47 | Permutations II |
60 | Permutation Sequence |
本文記錄下在刷題過程當中對於這個類題型的解法,但願對你們有所幫助。app
對於全排列的求解,第一個想到的確定是經過遞歸的解法。例如對於數列p(n)={1,2,3,…,n},從中間取出一個數好比1,剩下的只須要求出p(n-1)的全排列,而後依次把1加入p(n-1)的全排列中。對於全排列也有2中方法:.net
相信對於2個方法的描述,你們應該仍是比較模糊的。不要緊後續將會詳細講解。code
舉個例子,好比{1, 2 , 3 },咱們知道這個序列的全排列是:blog
{1,2,3}
{1,3,2}
{2,1,3}
{2,3,1}
{3,1,2}
{3,2,1}排序
觀察上面的結果,能夠發現只要把1插入到{2,3}和{3,2}的各個位置,就能夠得到答案。同時也能夠知道{2,3}和{3,2}實際上是除了1之外剩下的元素的全排列。遞歸
所以能夠總結出以下的步驟:get
實現的代碼以下:it
class Solution(object): def permute(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ if len(nums) == 0 : return [[]] ret = [] sub_permute = self.permute(nums[1:]) for e in sub_permute: for (index,x) in enumerate(e): t = list(e) t.insert(index,nums[0]) ret.append(t) t = list(e) t.append(nums[0]) ret.append(t) return ret
繼續上面那個例子{1,2,3}:
{1,2,3}
{1,3,2}
{2,1,3}
{2,3,1}
{3,1,2}
{3,2,1}
是否發現生成全排列的方式也能夠固定一個首元素,而後生成剩下的元素的排列,再將1和剩下的元素的排列作組合。
例如固定1 ,而後生成{2,3}的全排列是{2,3}和{3,2}。而後1和{2,3}和{3,2}組合。而後交換1和2 ,讓2作首元素,在生成{1,3}的全排列{1,3}和{3,1},在和2作組合。實現的代碼以下:
class Solution(object): def permute(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ return self.p(nums) def p(self,nums): if len(nums) == 1 : return [[nums[0]]] ret = [] for i in range(len(nums)): nums[0],nums[i] = nums[i],nums[0] t = self.p(nums[1:]) for e in t : t1 = list(e) t1.insert(0,nums[0]) ret.append(t1) nums[0],nums[i] = nums[i],nums[0] return ret
這裏直接引用文獻3全排列算法的全面解析中的圖來講明下字典序的方法。以下圖所示:
上面的4步既是求出了當前序列的下一個比它大的序列。所以,求一個序列的全排序,能夠從序列的最小排列開始,一直求到最大排列,既求得了全排列。
代碼實現以下:
class Solution(object): def islast(self,nums): for i in range(0,len(nums) - 1): if nums[i]<nums[i+1]: return False return True def permuteUnique(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ ret = [] nums.sort() tmp = list(nums) ret.append(tmp) first_index = 0 sec_index = 0 j = 0 while True : if self.islast(nums) == True: break for i in range(len(nums) - 2 , -1 ,-1): if nums[i]<nums[i+1]: first_index = i break for i in range(len(nums)-1, first_index, -1 ): if nums[i] > nums[first_index] : sec_index = i break nums[first_index],nums[sec_index] = nums[sec_index],nums[first_index] for i in range(first_index+1,len(nums)): if i<=len(nums) - 1 - (i-first_index-1): nums[i],nums[ len(nums) - 1 - (i-first_index-1) ] = nums[ len(nums) - 1 - (i-first_index-1) ],nums[i] tmp = list(nums) ret.append(tmp) first_index = 0 sec_index = 0 return ret