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
  • 相关阅读:
    华为防火墙server-map、ALG
    华为防火墙来回路径不一致、智能选路随笔
    锐捷交换机修改openssl秘钥加密算法
    华为交换机板卡类型
    H3C交换机堆叠口、MAD检测口
    内网用户使用公网IP访问内部服务
    记一次SSL证书排错
    解析teambition文件为分享链接
    tomcat启动乱码如何解决?
    BOM与DOM的区别与联系
  • 原文地址:https://www.cnblogs.com/mr-stn/p/8996779.html
Copyright © 2011-2022 走看看