原题是找到一组数的全排列
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> #
这个题大眼一看就是思路一大坨,这里做一个整理吧
思路1
比较直观的想法就是递归咯~~ 在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
- int N = num.size();
- vector<vector<int> > ret;
- if(N == 1){
- ret.push_back(num);
- return ret;
- }
- vector<vector<int> > post;
- vector<int> cur;
- vector<int> tmp;
- for(int i = 0; i < N; i++){
- cur = num;
- cur.erase(cur.begin()+i);
- post = permute(cur);
- for(int j = 0; j < post.size(); j++){
- tmp = post[j];
- tmp.insert(tmp.begin(), num[i]);
- ret.push_back(tmp);
- }
- }
- return ret;
- }
- };
思路2:
- class Solution {
- vector<vector<int> > ret;
- int N;
- public:
- void perm(vector<int> &num, int i){
- if( i == N){
- ret.push_back(num);
- }
- for(int j = i; j < N; j++){
- swap(num[i], num[j]);
- perm(num, i + 1);
- swap(num[j], num[i]);
- }
- }
- vector<vector<int> > permute(vector<int> &num) {
- // Start typing your C/C++ solution below
- // DO NOT write int main() function
- N = num.size();
- ret.clear();
- perm(num, 0);
- return ret;
- }
- };
思路3
- class Solution {
- public:
- void nextPermutation(vector<int> &num) {
- // Start typing your C/C++ solution below
- // DO NOT write int main() function
- //5,4,7,5,3,2
- // | |
- // i j
- //5,5,7,4,3,2
- //5,5,2,3,4,7
- int i = num.size()-1;
- while(i > 0 && num[i-1] >= num[i] ){
- i--;
- }
- int j = i;
- while(j < num.size() && num[j] > num[i-1]) j++;
- if(i == 0){
- reverse(num.begin(), num.end());
- }else{
- swap(num[i-1], num[j-1]);
- reverse(num.begin() + i, num.end());
- }
- }
- int factorial(int n){
- return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
- }
- vector<vector<int> > permute(vector<int> &num) {
- // Start typing your C/C++ solution below
- // DO NOT write int main() function
- int N = num.size();
- vector<vector<int> > ret;
- ret.push_back(num);
- for(int i = 1; i < factorial(N); i++){
- nextPermutation(num);
- ret.push_back(num);
- }
- return ret;
- }
- };
思路四
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
- class Solution {
- public:
- int factorial(int n){
- return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
- }
- void plusp(vector<int> &p, const vector<int> &bound){
- int i = p.size()-1;
- while(i >= 0){
- if(p[i] < bound[i]){
- p[i]++;
- break;
- }else{
- p[i] = 0;
- i--;
- }
- }
- }
- 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> ori_num = num;
- vector<int> tmp = num;
- int N = num.size();
- vector<int> p(N, 0);
- vector<int> bound = num;
- for(int i = 0; i < N; i++){
- bound[i] = N - 1 - i;
- }
- for(int i = 0; i < factorial(N); i++){
- num = ori_num;
- for(int j = 0; j < N; j++){
- tmp[j] = num[p[j]];
- num.erase(num.begin() + p[j]);
- }
- ret.push_back(tmp);
- plusp(p, bound);
- }
- return ret;
- }
- };
关于字典序的补充版本
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2]
have the following unique permutations:
[1,1,2]
, [1,2,1]
, and [2,1,1]
.
Permutations 的升级版,依旧是全排列问题,但是 序列中可能会出现重复数字 。
思路:采用字典序的非递归方法。 从字典顺序最小的一种排列开始,每次获得字典序刚好比前一个排列大的排列,直到得到字典序最大的排列时,就得到了所有的结果, 以字符串"abc"为例,"abc"是字典序最小的排列,所有情况按字典序排列为"abc","acb","bac","bca","cba","cab"。
具体步骤为为:
1.字符串进行排序,得到字符串的最小字典序排列(C0C1C2...Cn),Ci<=Ci+1。
2.从后往前,找到一对相邻的升序元素CiCi+1,(Ci<Ci+1),如果遍历完字符串找不到这样的相邻升序对,说明已经达到了字典序最大的全排列
3.从字符串结束位置到位置i遍历,找到比Ci大的元素Cj,交换Cj的位置
4.将Ci+1到Cn所有的字符逆序,这样得到的排列刚好比之前的字典序大(因为转换后Ci+1<Ci+2<...<Cn,为最小字典序)。
5.重复3,4,5过程直到字典序最大。
AC code:
class Solution {
public:
void swap(int &i,int &j) { int temp=i; i=j; j=temp; } vector<vector<int> > permuteUnique(vector<int> &num) { vector<vector<int>> res; int i,j,n=num.size(); sort(num.begin(),num.end()); res.push_back(num); while(true) { for(i=n-2;i>=0;i--) if(num[i]<num[i+1]) break; if(i<=-1) return res; for(j=n-1;j>i;j--) if(num[j]>num[i]) break; swap(num[i],num[j]); for(int k=i+1;k<(i+1+n)/2;k++) swap(num[k],num[n-(k-i)]); res.push_back(num); } } };