题目: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].
思路一(无重复元素):这是通过交换得到的全排列。
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int> > v;
ProduceArray(num, 0, v);
return v;
}
void ProduceArray(vector<int> data, int index, vector<vector<int> > &v)
{
int n = data.size();
if(index == n)
{
v.push_back(data);
return;
}
for(int i=index;i < n;i++)
{
swap(data[i], data[index]);
ProduceArray(data, index+1, v);
swap(data[i], data[index]);
}
}
};
注意:这种方法的缺点是如果序列中有重复元素,得到的排列也是有重复的。
思路二:第一种方法的思路是交换,第二种方法的思路就是插入。首先拿出原序列的第一个元素,然后将其插入到剩余序列中,有n种插入方法(得到的序列个数是原来的n倍)。递归地,剩余序列也可以这么做而得到。这也可以看作是一种分治策略,即把规模为N的原问题分解为规模为1的问题和规模为N的问题。
代码:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string insertCharAt(const string &word, char c, int i)
{
if(i<0 || i > word.size())
return word;
string left = word.substr(0, i);
string right = word.substr(i);
return left + c + right;
}
vector<string> genPermutation(const string &s)
{
vector<string> re;
if(s.size() == 1)
{
re.push_back(s);
return re;
}
char first = s[0];
string rest = s.substr(1);
vector<string> restwords = genPermutation(rest);
vector<string>::iterator it = restwords.begin();
for( ;it != restwords.end();it++)
{
for(int i=0;i<=(*it).size();i++)
{
re.push_back(insertCharAt((*it), first, i));
}
}
return re;
}
int main(int argc, const char * argv[])
{
string s = "abc";
vector<string> permutation = genPermutation(s);
cout<<permutation.size()<<endl;
vector<string>::iterator it = permutation.begin();
for(; it != permutation.end();it++)
cout<<(*it)<<endl;
return 0;
}
思路三(有重复元素):先利用hash给每种不同的数做计数统计,然后用backtrack方法。需要辅助空间。
class Solution {
public:
vector<vector<int> > permuteUnique(vector<int> &num) {
vector<vector<int> > v;
int n = num.size();
if(n == 0)
return v;
map<int, int> m;
for(int i=0;i<n;i++)
if(m.find(num[i]) == m.end())
m[num[i]] = 1;
else
m[num[i]]++;
vector<int> now;
backtrack(m, v, num, n, now, 0);
return v;
}
void backtrack(map<int, int> &m, vector<vector<int> > &v, vector<int> &num, int n, vector<int> now, int idx)
{
if(idx == n)
{
v.push_back(now);
return;
}
map<int, int>::iterator it = m.begin();
for(;it != m.end(); it++)
{
if((*it).second > 0)
{
(*it).second--;
now.push_back((*it).first);
backtrack(m, v, num, n, now, idx+1);
(*it).second++;
now.pop_back();
}
}
}
};