您的位置:首页 > 其它

leecode 解题总结:47. Permutations II

2017-02-10 00:13 453 查看
#include <iostream>
#include <stdio.h>
#include <vector>
#include <map>
#include <algorithm>

using namespace std;
/*
问题:
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],
[2,1,1]
]

分析:
这是典型的带有重复元素的排列问题。参见刘汝佳算法竞赛入门经典。
规避重复元素带来的排列重复的解决办法是:
1 判断前元素出现次数是否已经>=最大出现次数,如果是,说明不符合
2
map<int ,int> numToTimes;
int times;
int count;
for(int i = 0 ; i < size ; i++)
{
value = nums.at(i);
times = numToTimes[value];
count = 0;
for(int j = 0 ; j < pos ; j++)
{
if( nums.at(j) == value )
{
count++;
}
}
//次数全部用完,不符合条件
if(count >= times)
{
}
}

输入:
3(数组元素个数)
1 1 2
3
1 2 1
输出:
1 1 2,1 2 1,2 1 1
1 2 1,1 1 2,2 1 1

关键:
1 要明确,存在重复摆放的是nums.at(i-1)和nums.at(i)都尝试为result.at(pos)进行元素摆放,必须确保相邻元素nums.at(i-1)和nums.at(i)不同
for(i = 0 ; i < size ; i++)
{
value = nums.at(i);
times = numToTimes[value];
count = 0;

//要明确,存在重复摆放的是nums.at(i-1)和nums.at(i)都尝试为result.at(pos)进行元素摆放,必须确保相邻元素nums.at(i-1)和nums.at(i)不同
if(!i || ( nums.at(i-1) != nums.at(i) ))
{
for(int j = 0 ; j < pos ; j++)
{
if( result.at(j) == value )
{
count++;
}
}
//判断是否是相邻两个元素重复出现,需要判断当前元素和之前上一个选择的元素是否相同,result.at(i-1)是前一个选择元素,value是当前选择的元素
//次数全部用完,不符合条件
if(count >= times)
{
continue;
}
else
{
result.push_back(value);
getPermutation(nums , pos + 1 , results , result , numToTimes);
//回溯
result.pop_back();
}
}
}
*/

class Solution {
public:
void getPermutation(vector<int>& nums , int pos , vector< vector<int> >& results , vector<int>& result , map<int , int>& numToTimes)
{
if(nums.empty() || pos < 0)
{
return;
}
if(pos == nums.size())
{
results.push_back(result);
return;
}
int size = nums.size();
int times;
int count;
int value;
int i;
int len;
for(i = 0 ; i < size ; i++)
{
value = nums.at(i);
times = numToTimes[value];
count = 0;

//要明确,存在重复摆放的是nums.at(i-1)和nums.at(i)都尝试为result.at(pos)进行元素摆放,必须确保相邻元素nums.at(i-1)和nums.at(i)不同
if(!i || ( nums.at(i-1) != nums.at(i) ))
{
for(int j = 0 ; j < pos ; j++)
{
if( result.at(j) == value )
{
count++;
}
}
//判断是否是相邻两个元素重复出现,需要判断当前元素和之前上一个选择的元素是否相同,result.at(i-1)是前一个选择元素,value是当前选择的元素
//次数全部用完,不符合条件
if(count >= times)
{
continue;
}
else
{
result.push_back(value);
getPermutation(nums , pos + 1 , results , result , numToTimes);
//回溯
result.pop_back();
}
}
}
}

vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> results;
if(nums.empty())
{
return results;
}
//对nums排序,使得重复元素相邻摆放,避免后续产生重复排列
sort(nums.begin() , nums.end());
vector<int> result;
map<int , int> numToTimes;
int size = nums.size();
for(int i = 0 ; i < size ; i++)
{
if(numToTimes.find( nums.at(i) ) != numToTimes.end())
{
numToTimes[nums.at(i)]++;
}
else
{
numToTimes[nums.at(i)] = 1;
}
}
getPermutation(nums , 0 , results , result , numToTimes);
return results;
}
};

void print(vector< vector<int> >& results)
{
if(results.empty())
{
cout << "no result" << endl;
return;
}
int size = results.size();
int len;
for(int i = 0 ; i < size ; i++)
{
len = results.at(i).size();
for(int j = 0 ; j < len ; j++)
{
cout << results.at(i).at(j) << " ";
}
cout << ",";
}
cout << endl;
}

void process()
{
int num;
int value;
vector<int> nums;
Solution solution;
vector< vector<int> > results;
while(cin >> num)
{
nums.clear();
for(int i = 0 ; i < num  ; i++)
{
cin >> value;
nums.push_back(value);
}
results = solution.permuteUnique(nums);
print(results);
}
}
int main(int argc , char* argv[])
{
process();
getchar();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: