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 };

 

posted @ 2018-05-05 23:34  赖兴宇  阅读(3360)  评论(0编辑  收藏  举报