Permutations

Permutations Mar 17 '12

Given a collection of numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2], and [3,2,1].

思路一:因为上面写过nextPermutations函数,很自然想到可以直接用这个函数辅助实现,代码如下:

class Solution {
public:
    int factorial(int n)
    {
        return (n==1)?1:n*factorial(n-1);
    }
    
    void nextPermutation(vector<int> &num) {  
        int i = 0;  
        int k = num.size();  
          
        while(k-->=1)  
        {  
            if(num[k] > num[k-1])  
            {  
                i = k;  
                break;  
            }  
        }  
        int j= i-1;  
        k = num.size();  
        while(k-- != i-1)  
        {  
            if(num[k] > num[i-1]) {  
                j = k;  
                break;  
            }  
        }            
        swap(num[i-1],num[j]);      
          
        reverse(num.begin()+i,num.end());  
    }  
    
    vector<vector<int> > permute(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        vector<vector<int>> ret;
        
        int N = factorial(num.size());
        for(int i = 0;i < N;i++){
            ret.push_back(num);
            nextPermutation(num);
        }
        return ret;
    }
};

76 milli secs


思路二:递归。每次从num中拿出1个数字放在第一个,然后剩下的数字递归做全排列。

class Solution {
public:
    vector<vector<int> > permute(vector<int> &num) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function    
        vector<vector<int>> ret;
        vector<int> vec;

        gen_permute(ret,num,vec);
        
        return ret;
        
    }
    
    
    void gen_permute(vector<vector<int>>& ret,vector<int> &num,vector<int> &vec)
    {
        if(num.size() == 0) {
            ret.push_back(vec);
    		vec.clear();
            return;
        }


        vector<int>::iterator it = num.begin();
        while(it != num.end()) 
        {
            vector<int> temp(vec);
            int tmp = *it;

            it = num.erase(it);
			temp.push_back(tmp);
            gen_permute(ret,num,temp);
            it = num.insert(it,tmp);
            it++;
        }
    }
};

92 milli secs


其余思路有空再实现,转一个讨论

 

[leetcode] permutations的讨论

  88人阅读  评论(1)  收藏  举报

原题是酱紫的,其实就是找到一组数的全排列啦

Given a collection of numbers, return all possible permutations.

For example,
[1,2,3] have the following permutations:
[1,2,3][1,3,2][2,1,3][2,3,1][3,1,2], and [3,2,1].

函数原型:

vector<vector<int> > permute(vector<int> &num;


这个题大眼一看就是思路一大坨,这里做一个整理吧


思路1

比较直观的想法就是递归咯~~ 在num中拿出1个数字放在第一个,然后剩下的数字做一个全排列,最早接触这个问题的时候我就是这么写的


[cpp]  view plain copy
  1. class Solution {  
  2. public:  
  3.     vector<vector<int> > permute(vector<int> &num) {  
  4.         // Start typing your C/C++ solution below  
  5.         // DO NOT write int main() function  
  6.         int N = num.size();  
  7.         vector<vector<int> > ret;  
  8.           
  9.         if(N == 1){  
  10.             ret.push_back(num);  
  11.             return ret;  
  12.         }  
  13.         vector<vector<int> > post;  
  14.           
  15.         vector<int> cur;  
  16.         vector<int> tmp;  
  17.           
  18.         for(int i = 0; i < N; i++){  
  19.             cur = num;  
  20.             cur.erase(cur.begin()+i);  
  21.             post = permute(cur);  
  22.             for(int j = 0; j < post.size(); j++){  
  23.                 tmp = post[j];  
  24.                 tmp.insert(tmp.begin(), num[i]);  
  25.                 ret.push_back(tmp);  
  26.             }  
  27.         }  
  28.           
  29.         return ret;  
  30.     }  
  31. };  

思路2:
建立一棵树,比如说
        1234
1234    2134   3214    4231     //就是swap(1,1)  swap(1,2) swap(1,3) swap(1,4)
    |          
234  324  432
   |
34 43
然后捏,就用DFS遍历一下,叶子节点就是我们想要的啦

[cpp]  view plain copy
  1. class Solution {  
  2.       
  3.     vector<vector<int> > ret;  
  4.     int N;  
  5.       
  6. public:  
  7.     void perm(vector<int> &num, int i){  
  8.         if( i == N){  
  9.             ret.push_back(num);  
  10.         }  
  11.           
  12.         for(int j = i; j < N; j++){  
  13.             swap(num[i], num[j]);  
  14.             perm(num, i + 1);  
  15.             swap(num[j], num[i]);  
  16.         }  
  17.     }  
  18.   
  19.   
  20.     vector<vector<int> > permute(vector<int> &num) {  
  21.         // Start typing your C/C++ solution below  
  22.         // DO NOT write int main() function  
  23.         N = num.size();  
  24.         ret.clear();  
  25.           
  26.         perm(num, 0);  
  27.           
  28.         return ret;  
  29.           
  30.     }  
  31. };  

思路3
stl的algorithm里面其实是有next permutation的算法的,那其实用next permutation的方法也是一个不错的选择
next permutation的算法就是。。。swap + reverse。。。
[cpp]  view plain copy
  1. class Solution {  
  2. public:  
  3.      void nextPermutation(vector<int> &num) {  
  4.         // Start typing your C/C++ solution below  
  5.         // DO NOT write int main() function  
  6.           
  7.         //5,4,7,5,3,2  
  8.         //    |     |  
  9.         //    i     j  
  10.         //5,5,7,4,3,2  
  11.         //5,5,2,3,4,7  
  12.         int i = num.size()-1;  
  13.         while(i > 0 && num[i-1] >= num[i] ){  
  14.             i--;  
  15.         }  
  16.           
  17.         int j = i;  
  18.           
  19.         while(j < num.size() && num[j] > num[i-1]) j++;  
  20.           
  21.         if(i == 0){  
  22.             reverse(num.begin(), num.end());  
  23.         }else{  
  24.             swap(num[i-1], num[j-1]);  
  25.             reverse(num.begin() + i, num.end());  
  26.         }  
  27.           
  28.           
  29.     }  
  30.       
  31.     int factorial(int n){  
  32.         return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;  
  33.     }  
  34.   
  35.   
  36.     vector<vector<int> > permute(vector<int> &num) {  
  37.         // Start typing your C/C++ solution below  
  38.         // DO NOT write int main() function  
  39.         int N = num.size();  
  40.         vector<vector<int> > ret;  
  41.           
  42.         ret.push_back(num);  
  43.           
  44.         for(int i = 1; i < factorial(N); i++){  
  45.             nextPermutation(num);  
  46.             ret.push_back(num);  
  47.         }  
  48.           
  49.         return ret;  
  50.           
  51.     }  
  52. };  

思路四
我觉得思路4是一个很常规的思路,很多把recursive的code改成iterative的code都会用到这样的方法,其实呢,它的本质就是把N个for改成while的方法。介个方法在编程之美里面的“电话号码”那一节提到过,不明白的童鞋可以去看一看,我觉得第一次想写粗来还是很难的,不过多写几个,就会很熟练啦

对应介个题目的思路捏就是。。。举个例子来说吧
如果我想求1,2,3,4的全排列
偶的思路就是建一个特殊的数,它的进位方法是 3, 2, 1, 0
所以,这个数的++过程就是
0000 -> 0010 -> 0100 -> 0110 ->0200 -> 0210 -> 

1000 -> 1010 -> 1100 -> 1110 ->1200 -> 1210 -> 

2000 -> 2010 -> 2100 -> 2110 ->2200 -> 2210 -> 

3000 -> 3010 -> 3100 -> 3110 ->3200 -> 3210

哇哈哈哈,刚好是24个!

然后捏? b0 b1 b2 b3就代表在当前剩下的数字中选择第bi个

哇!好复杂。。。

比如0210

0: 在1234中选择第0个,就是1

2: 在234中选择滴2个,就是4

1: 在23中选择第1个,就是3

0: 在2中选择第0个,就是2

所以0210对应点就素 1432

[cpp]  view plain copy
  1. class Solution {  
  2. public:  
  3.     int factorial(int n){  
  4.         return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;  
  5.     }  
  6.       
  7.     void plusp(vector<int> &p, const vector<int> &bound){  
  8.         int i = p.size()-1;  
  9.         while(i >= 0){  
  10.             if(p[i] < bound[i]){  
  11.                 p[i]++;  
  12.                 break;  
  13.             }else{  
  14.                 p[i] = 0;  
  15.                 i--;  
  16.             }  
  17.         }  
  18.           
  19.     }  
  20.       
  21.       
  22.       
  23.     vector<vector<int> > permute(vector<int> &num) {  
  24.         // Start typing your C/C++ solution below  
  25.         // DO NOT write int main() function  
  26.         vector<vector<int> > ret;  
  27.         vector<int> ori_num = num;  
  28.         vector<int> tmp = num;  
  29.           
  30.         int N = num.size();  
  31.           
  32.         vector<int> p(N, 0);  
  33.           
  34.         vector<int> bound = num;  
  35.         for(int i = 0; i < N; i++){  
  36.             bound[i] = N - 1 - i;  
  37.         }  
  38.           
  39.         for(int i = 0; i < factorial(N); i++){  
  40.             num = ori_num;  
  41.             for(int j = 0; j < N; j++){  
  42.                 tmp[j] = num[p[j]];  
  43.                 num.erase(num.begin() + p[j]);  
  44.             }  
  45.             ret.push_back(tmp);  
  46.             plusp(p, bound);  
  47.               
  48.         }  
  49.           
  50.         return ret;  
  51.           
  52.     }  
  53. };  

http://blog.youkuaiyun.com/tuantuanls/article/details/8717262







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值