leetcode 46. 全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [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 };
有疑惑或者更好的解决方法的朋友,可以联系我,大家一起探讨。qq:1546431565