zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    how to uninstall devkit
    asp.net中bin目录下的 dll.refresh文件
    查找2个分支的共同父节点
    Three ways to do WCF instance management
    WCF Concurrency (Single, Multiple, and Reentrant) and Throttling
    检查string是否为double
    How to hide TabPage from TabControl
    获取当前系统中的时区
    git svn cygwin_exception
    lodoop打印控制具体解释
  • 原文地址:https://www.cnblogs.com/mr-stn/p/8996779.html
Copyright © 2011-2022 走看看