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]
.
方法一,先对原数组进行sort,然后利用next_permutation算法依次计算每一个permutation并添加到结果中。时间O(n!),空间O(1)。
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int> > result;
std::sort(num.begin(), num.end());
do {
result.push_back(num);
}while(next_permutation(num));
return result;
}
bool next_permutation(vector<int> &num)
{
const int n = num.size();
int i = n-1, k = n-1;
for(; i>0; i--)
{
if(num[i-1] < num[i])
break;
}
if(i == 0) return false;
for(; k>=i; k--)
if(num[k] > num[i-1])
break;
swap(num[i-1], num[k]);
reverse(num.begin()+i, num.end());
return true;
}
};
方法二,DFS递归。每次加入不在Path中的一个元素。
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
//sort(num.begin(), num.end());
vector<vector<int> > result;
vector<int> path;
dfs(num, path, result);
return result;
}
void dfs(vector<int> &num, vector<int> &path, vector<vector<int> > &result)
{
if(path.size() == num.size())
{
result.push_back(path);
return;
}
for(int i=0; i<num.size(); ++i)
{
auto pos = find(path.begin(), path.end(), num[i]);
if(pos == path.end())
{
path.push_back(num[i]);
dfs(num, path, result);
path.pop_back();
}
}
}
};
算法3: 一个更好的DFS思路不需要使用临时变量path,针对每个位置i,从i到end的元素中选出一个和第i个位置进行交换,然后针对第i+1个位置进行递归。
递归后再恢复交换之前的位置。
class Solution {
public:
vector<vector<int> > permute(vector<int> &num)
{
vector<vector<int> > result;
vector<int> path;
dfs(num, 0, result);
return result;
}
void dfs(vector<int> &num, int begin, vector<vector<int> > &result)
{
if(begin == num.size())
{
result.push_back(num);
return;
}
for(int i=begin; i<num.size(); ++i)
{
int tmp = num[begin];
num[begin] = num[i];
num[i] = tmp;
dfs(num, begin+1, result);
tmp = num[begin];
num[begin] = num[i];
num[i] = tmp;
}
}
};