您的位置:首页 > 其它

[Leetcode]Permutations && Permutations II

2014-11-26 10:19 435 查看
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]
.
组合的题目,第一题无重复,第二题有重复。

自我感觉最常规的方法就是回溯法,两道题都试用。第一道没有重复的情况下还可以有更取巧的办法,第二题貌似只能用回溯法。

先看第一题。

用回溯法,假设一共n个数字,对结果中的每一位元素i,都要把所有数字带进去试一下,只要不和前面的数字重复就OK。

class Solution {
public:
vector<vector<int> > result;
vector<vector<int> > permute(vector<int> &num) {
int n = num.size();
vector<int> oneAnswer;
searchAnswer(oneAnswer,num,n,0);
return result;
}
void searchAnswer(vector<int> &oneAnswer,vector<int> num,int n,int index){
for (int i = 0; i < n;i++){
if (!repeat(oneAnswer,num[i])){
oneAnswer.push_back(num[i]);
if (oneAnswer.size() == n){
result.push_back(oneAnswer);
oneAnswer.pop_back();
return;
}
searchAnswer(oneAnswer,num,n,index+1);
oneAnswer.pop_back();
}
}
}
bool repeat(vector<int> oneAnswer,int x){
for (int i = 0; i < oneAnswer.size(); i++){
if (x == oneAnswer[i]){
return true;
}
}
return false;
}
};还有一种方法就是类似建立一个树。
最后排列的结果,第一个元素可能有四种情况,那就将1、2、3、4个元素分别和第一个元素交换位置,每个元素交换位置之后为了方便下一个元素交换,要先把位置换回去,也就是回到数组的初始状态。然后是第二个元素和后面的元素交换。 

class Solution{
public:
vector<vector<int> > permute(vector<int> &num){
vector<vector<int> > result;
dfs(result,num,0);
return result;
}
void dfs(vector<vector<int> > &result,vector<int> &num,int cur){
if(cur == num.size()){
result.push_back(num);
}
else{
for(int i = cur;i < num.size();i++){
swap(num[i],num[cur]);
dfs(result,num,cur+1);
swap(num[i],num[cur]);
}
}
}
};


然后是第二题。
[1,1,2]
 have
the following unique permutations:
[1,1,2]
[1,2,1]
,
and 
[2,1,1]
.

第二题数组中有重复元素,那就不能像第一题那样使用回溯条件了。

1、在每一步迭代(或者说结果的每一个位置上)中,出现过的元素就不能再出现了。比如说上边的例子,第一个位置是元素第一个1,那么第二个1就不能出现在这个位置上。因此,我们给每一位设置一个出现过的元素数组vector<int> used,来保存已经出现的元素,这些元素是不能再一次出现在这个位置上的。

2、在上面条件满足的基础上,不同位置上是可以出现重复元素的,因此不能像第一题中那样再去检查元素是否重复了。元素可以重复,但是他们的下标是不能重复的。因此我们在用一个vector<int> indexUsed,来保存出现过的元素下标就可以了。

class Solution {
public:
vector<vector<int> > result;
vector<vector<int> > permuteUnique(vector<int> &num) {
int n = num.size();
vector<int> oneAnswer;
vector<int> indexUsed;
searchAnswer(oneAnswer, num, indexUsed, n, 0);
return result;
}
void searchAnswer(vector
4000
<int> &oneAnswer, vector<int> num,vector<int> indexUsed, int n, int index){
vector<int> used;
for (int i = 0; i < n; i++){
if (!repeat(used, num[i])&&!repeat(indexUsed,i)){
used.push_back(num[i]);
oneAnswer.push_back(num[i]);
indexUsed.push_back(i);
if (oneAnswer.size() == n){
result.push_back(oneAnswer);
oneAnswer.pop_back();
indexUsed.pop_back();
return;
}
searchAnswer(oneAnswer, num, indexUsed, n, index + 1);
oneAnswer.pop_back();
indexUsed.pop_back();
}
}
}
bool repeat(vector<int> oneAnswer, int x){
for (int i = 0; i < oneAnswer.size(); i++){
if (x == oneAnswer[i]){
return true;
}
}
return false;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode BackTrack