47. Permutations II&8.8Permutations with Duplicates
2014-03-06 15:09
411 查看
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
and
套用了Next Permutation中的代码
程序员面试金典的解法
这个问题与http://blog.csdn.net/sjt19910311/article/details/45345599类似,但是我们可能在字符串中碰到可能重复的字符。
解决这个问题的一个简单方法是跟前面的问题一样,检查一个排列是不是之前已经被创建。如果没有,就把它加入列表中。一个简单的哈希表就可以解决这个问题。这种方法的时间复杂度在最坏情况下(实际上,任何情况下都)是。
虽然我们无法改变最坏情况下的时间复杂度,但是我们应该设计一个在大多数情况下可以好于的算法。考虑一个像这样,所有字符都相同的字符串。这将会耗费非常长的时间(因为一个13个字符的字符串,有超过60亿个排列)。虽然实际上只有一个唯一的排列。
理想地,我们只想得到这唯一的排列,而不是得到所有的排列,然后再排除那些重复的。
我们可以从计算每个字符出现的次数入手(使用哈希表可以非常容易做到)。对一个字符串,例如,将会得到
让我们考虑产生这个字符串(哈希表表示的)一个排列。我们要做的第一个选择是选择a、b还是c作为第一个字符。然后,我们有一个子问题要解决:找到所有余下的字符的所有排列,然后将它们追加到已经选定的“前缀”后面。
最终,我们不会再有余下的字符。
For example,
[1,1,2]have the following unique permutations:
[1,1,2],
[1,2,1],
and
[2,1,1].
套用了Next Permutation中的代码
class Solution { public: vector<vector<int> > permuteUnique(vector<int> &num) { vector<vector<int> > res; vector<int> tmp = num; do{ res.push_back(num); nextPermutation(num); }while(num != tmp); return res; } void nextPermutation(vector<int> &num) { int iMax = -1; for(int i = num.size() - 1;i >= 1;i--) if(num[i-1] < num[i]) { iMax = i; break; } int jMax = -1; for(int j = num.size() -1 ;j >= iMax;j--) if(num[iMax -1] < num[j]) { jMax = j; break; } if(iMax != -1 and jMax != -1) { swap(num[iMax -1],num[jMax]); reverse(num.begin()+iMax,num.end()); } //f such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). else reverse(num.begin(),num.end()); } };
程序员面试金典的解法
这个问题与http://blog.csdn.net/sjt19910311/article/details/45345599类似,但是我们可能在字符串中碰到可能重复的字符。
解决这个问题的一个简单方法是跟前面的问题一样,检查一个排列是不是之前已经被创建。如果没有,就把它加入列表中。一个简单的哈希表就可以解决这个问题。这种方法的时间复杂度在最坏情况下(实际上,任何情况下都)是。
虽然我们无法改变最坏情况下的时间复杂度,但是我们应该设计一个在大多数情况下可以好于的算法。考虑一个像这样,所有字符都相同的字符串。这将会耗费非常长的时间(因为一个13个字符的字符串,有超过60亿个排列)。虽然实际上只有一个唯一的排列。
理想地,我们只想得到这唯一的排列,而不是得到所有的排列,然后再排除那些重复的。
我们可以从计算每个字符出现的次数入手(使用哈希表可以非常容易做到)。对一个字符串,例如,将会得到
让我们考虑产生这个字符串(哈希表表示的)一个排列。我们要做的第一个选择是选择a、b还是c作为第一个字符。然后,我们有一个子问题要解决:找到所有余下的字符的所有排列,然后将它们追加到已经选定的“前缀”后面。
最终,我们不会再有余下的字符。
class Solution { public: unordered_map<int,int> buildFreqTable(vector<int>& nums) { unordered_map<int,int> freqMap; for(int i = 0;i<nums.size();++i) { freqMap[nums[i]]++; } return freqMap; } void getPerms(unordered_map<int,int> freqMap,vector<int> prefix,int remaining, vector<vector<int>> &ret) { if(remaining == 0) { ret.push_back(prefix); return; } for(unordered_map<int,int>::iterator it = freqMap.begin();it != freqMap.end();++it) { int count = it->second; if(count > 0) { freqMap[it->first] = count -1; prefix.push_back(it->first); getPerms(freqMap,prefix,remaining-1,ret); prefix.pop_back(); freqMap[it->first] = count; } } } vector<vector<int>> permuteUnique(vector<int>& nums) { vector<vector<int> > ret; unordered_map<int,int> freqMap = buildFreqTable(nums); vector<int> prefix; getPerms(freqMap,prefix,nums.size(),ret); return ret; } };
相关文章推荐
- memcache基本方法
- 搞IOS7SDK的UI适配工作
- 查询当前用户能访问哪些数据库
- float和double变量的内存布局~~~~~~
- Robotium自动化测试利用InstrumentationTestRunner和XmlSerializer导出xml报告到手机里
- 自己动手编写一个VS插件(三)——创建工具栏之一
- 详细剖析GET/POST提交如何编码以及服务器如何解码以及乱码解决方案
- C#&JQuery非缓存式无刷新临时存储数据之仿购物车功能
- [0] 解决版本冲突-使用SVN主干与分支功能
- tcpdump抓取ftp密码
- Java多线程几个例子学习
- Android平台下RFID模块测试程序
- java比较器comparator使用示例分享
- 你好
- 不可混为一谈 说说数字机顶盒与网络机顶盒
- 自己动手编写一个VS插件(二)——理解OnConnection函数
- 天秤座特质
- 不重启Mysql修改root密码的方法
- 网站收藏
- 在Windows操作系统下通过PL/SQL连接到VM中Linux安装的Oracle