給定一個沒有重復數字的序列,返回其所有可能的全排列。
示例:
輸入: [1,2,3] 輸出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
思路:遞歸的思路來實現,即固定第一位,對剩下的數字進行同樣的算法,知道把一個數組全部遍歷完。
用vector<vector<int>>& ans來保存全排列的數組, 用begin來表示需要全排列的起始位置,end來表示需要全排列的終止位置
很明顯可以看出這種算法的復雜度為O(n!),第一位需要交換n次, 第二位需要交換n-1次,....
上面說的固定,其實就是遞歸的交換第i位
可以發現程序中有兩個swap(nums, begin, i)的調用,首先這是交換nums中的begin,i之間的數字。 再者調用兩次是把數組還原,以便保證下一個排列的正確性
用1,2,3來解釋這個程序,最開始的時候begin=0, end = 2;(end始終是數組的最后一位的下標)
permute(nums, ans, 0, 2)
i=0; //交換第一位
swap(nums,0,0); nums=1,2,3
permute(nums, ans, 1, 2)
i=1;
swap(nums, 1, 1); nums=1,2,3
permute(nums, ans, 2, 2)
ans.push(nums); ans=[[1,2,3]]
//完成一個完整的排列后,把數組還原到上一個狀態,這個完整的排列是針對遞歸中的每一個子列而言的,而不是對整個數列而言的
swap(nums, 1, 2); nums=1,2,3
i=2;
swap(nums, 1, 2); nums=1,3,2
permute(nums, ans, 2, 2)
ans.push(nums); ans=[[1,2,3],[1,3,2]]
swap(nums, 1, 2); nums=1,2,3
swap(nums, 0, 0) nums=1,2,3
i=1;
swap(nums, 0, 1); nums=2,1,3
permute(nums, ans, 1, 2);
i=1;
swap(nums, 1, 1); nums = 2,1,3
permute(nums, ans, 2, 2);
ans.push_back(nums); ans=[[1,2,3], [1,3,2], [2,1,3]]
swap(nums, 1, 1); nums = 2,1,3
i=2;
swap(nums, 1, 2); nums=2,3,1
permute(nums, ans, 2, 2);
ans.push_back(nums); ans=[[1,2,3], [1,3,2], [2,1,3], [2,3,1]]
swap(nums, 1, 2); nums=2,1,3
swap(nums, 0, 1); nums=1,2,3
i=2;
swap(nums, 0, 2); nums=3,2,1
permute(nums, ans, 1, 2);
i = 1;
swap(nums, 1, 1); nums=3,2,1
permute(nums, ans, 2, 2);
ans.push_back(nums); ans=[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,2,1]]
swap(nums, 1, 1); nums=3,2,1
i = 2;
swap(nums, 1, 2); nums=3,1,2
permute(nums, ans, 2, 2);
ans.push_back(nums); ans=[[1,2,3],[1,3,2],[2,1,3],[3,2,1],[3,1,2]]
swap(nums, 1, 2); nums=3,2,1
swap(nums, 0, 2); nums=1,2,3
結合上面的遞歸分析和下面的程序就很容易理解這個遞歸的算法
1 class Solution { 2 public: 3 void permute(vector<int>&nums, vector<vector<int>>& ans, int begin, int end){ 4 if(begin == end){//完成一次完整的排列,就把此時的nums壓入到ans中 5 ans.push_back(nums); 6 return; 7 }else{ 8 for(int i = begin; i <= end; i++){ 9 swap(nums, begin, i); 10 permute(nums, ans, begin+1, end);//對剩下的元素進行全排列 11 swap(nums, begin, i); //還原數組 12 } 13 } 14 } 15 16 void swap(vector<int>& nums, int k, int i){ 17 int temp = nums[k]; 18 nums[k] = nums[i]; 19 nums[i] = temp; 20 } 21 22 vector<vector<int>> permute(vector<int>& nums) { 23 vector<vector<int>> ans; 24 int len = nums.size()-1; 25 permute(nums, ans, 0, len); 26 return ans; 27 } 28 };
nums按值傳遞,會讓代碼更加簡便,按值傳遞不會改變nums原來的排列,因而不需要多余的一次swap來使其恢復原來的排列。
1 class Solution { 2 public: 3 void permute(vector<int>nums, vector<vector<int>>& ans, int begin, int end){ 4 if(begin > end){ 5 ans.push_back(nums); 6 return; 7 }else{ 8 for(int i = begin; i <= end; i++){ 9 swap(nums[begin], nums[i]); 10 permute(nums, ans, begin+1, end); 11 } 12 } 13 } 14 15 16 17 vector<vector<int>> permute(vector<int>& nums) { 18 vector<vector<int>> ans; 19 int len = nums.size()-1; 20 permute(nums, ans, 0, len); 21 return ans; 22 } 23 };
