LeetCode Permutations I && II
来源:互联网 发布:淘宝客做爆款 编辑:程序博客网 时间:2024/05/29 03:16
Permutations
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]
.
Permutations II
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]
, and [2,1,1]
.
不用修改,就两个问题都适用的算法,调用STL就行的。运行速度还是很快的。
class Solution {public: vector<vector<int> > permuteUnique(vector<int> &num) { vector<vector<int> > permu;sort(num.begin(), num.end());permu.push_back(num);while (next_permutation(num.begin(), num.end())){permu.push_back(num);}return permu;}};
但是感觉做这些算法题,直接调用STL是不是有点感觉是作弊的嫌疑,呵呵O(∩_∩)O~
下面看看不使用STL如何做。
Permutations:
回溯法:
代码出自这个blog: http://blog.csdn.net/tuantuanls/article/details/8717262
只有手动走几遍吧,就能理解了。
这个算法是最简单的了
vector<vector<int> > ret;int N;void perm(vector<int> &num, int i){if( i == N){ret.push_back(num);}for(int j = i; j < N; j++){swap(num[i], num[j]);perm(num, i + 1);swap(num[j], num[i]);}}vector<vector<int> > permute3(vector<int> &num) {N = num.size();ret.clear();perm(num, 0);return ret;}
下面我用先序遍历树的思想写的代码,画个树理解就好了:
如第一次遍历:访问abc节点,取出a放入结果中,从abd节点到访问bc节点,访问节点c,把b放入结果中,最后访问c,把c放入结果中,每一条路径就是一个解,这里总共有6条路径,刚好是六个解。遍历完,答案就出来了。
和前面的回溯思想有一点差别,但是最基本思想差不多是一致的,要把这些思想融合起来,做到融会贯通!
//5===============vector<vector<int> > permute5(vector<int> &num) {vector<int> mediRes;vector<vector<int> > res;permu(num, mediRes, res);return res;}void permu(vector<int> &num, vector<int> &mediRes, vector<vector<int> > &ret){int N = num.size();if (N == 1){mediRes.push_back(num[0]);ret.push_back(mediRes);mediRes.pop_back();return;}for (int i = 0; i < N; i++){mediRes.push_back(num[i]);vector<int> cur = num;cur.erase(cur.begin()+i);permu(cur, mediRes, ret);mediRes.pop_back();//注意:别忘记了这里需要弹出,不要等到循环结束}}
Permutations II
这个问题主要就增加防止重复的判断就可以了。
两种方法:
1 使用sort排序,然后排除相邻的重复数字。注意没排序的不可以这么判断
2 利用一个新的容器,装已经处理的数字,不重复处理数字,利用map和set等都可以。
方法一程序:
vector<vector<int> > permuteUnique2(vector<int> &num) {mediRes.clear();res.clear();sort(num.begin(), num.end());permuII2(num);return res;}void permuII2(vector<int> &num){int m = num.size();if (m == 1){mediRes.push_back(num[0]);res.push_back(mediRes);mediRes.pop_back();return;}//如果已经排序了的就可以值处理相邻的重复了for (int i = 0; i < m; i++){while (i < m-1 && num[i] == num[i+1]) i++;mediRes.push_back(num[i]);vector<int> cur = num;cur.erase(cur.begin()+i);permuII2(cur);mediRes.pop_back();//注意:别忘记了这里需要弹出,不要等到循环结束}}
vector<vector<int> > res;vector<int> mediRes;vector<vector<int> > permuteUnique(vector<int> &num) {mediRes.clear();res.clear();permuII(num);return res;}void permuII(vector<int> &num){int m = num.size();if (m == 1){mediRes.push_back(num[0]);res.push_back(mediRes);mediRes.pop_back();return;}//注意:不能光判断相邻的是否重复,不相邻的重复也会出现重复结果的。//脑子要放大unordered_set<int> used;for (int i = 0; i < m; i++){if (used.find(num[i]) == used.end()){mediRes.push_back(num[i]);vector<int> cur = num;cur.erase(cur.begin()+i);permuII(cur);mediRes.pop_back();//注意:别忘记了这里需要弹出,不要等到循环结束used.insert(num[i]);}}}
2013.12.12Update更新一个特别的方法:
参考博客:
http://blog.csdn.net/tuantuanls/article/details/8717262
思路四
我觉得思路4是一个很常规的思路,很多把recursive的code改成iterative的code都会用到这样的方法,其实呢,它的本质就是把N个for改成while的方法。介个方法在编程之美里面的“电话号码”那一节提到过,不明白的童鞋可以去看一看,我觉得第一次想写粗来还是很难的,不过多写几个,就会很熟练啦
对应介个题目的思路捏就是。。。举个例子来说吧
如果我想求1,2,3,4的全排列
偶的思路就是建一个特殊的数,它的进位方法是 3, 2, 1, 0
所以,这个数的++过程就是
0000 -> 0010 -> 0100 -> 0110 ->0200 -> 0210 ->
1000 -> 1010 -> 1100 -> 1110 ->1200 -> 1210 ->
2000 -> 2010 -> 2100 -> 2110 ->2200 -> 2210 ->
3000 -> 3010 -> 3100 -> 3110 ->3200 -> 3210
哇哈哈哈,刚好是24个!
然后捏? b0 b1 b2 b3就代表在当前剩下的数字中选择第bi个
哇!好复杂。。。
比如0210
0: 在1234中选择第0个,就是1
2: 在234中选择滴2个,就是4
1: 在23中选择第1个,就是3
0: 在2中选择第0个,就是2
所以0210对应点就素 1432
class Solution {public:int factorial(int n){int res = 1;for (int i = 2; i <= n; i++){res *= i;}return res;}void addOne(vector<int> &table, const vector<int> &bound){for (int i = table.size()-2; i >= 0; i--){//可以是==的所以是>不是>=if (++table[i] > bound[i]) table[i] = 0;else break;}}vector<vector<int> > permute(vector<int> &num) { int n = num.size();vector<vector<int> > res;if (n < 1) return res;vector<int> medRes(n);vector<int> temp(n);vector<int> table(n);vector<int> bound(n);for (int i = 0; i < n; i++){bound[i] = n-1-i;}int fac = factorial(n);for (int i = 0; i < fac; i++){temp = num;for (int j = 0; j < n; j++){medRes[j] = temp[table[j]];temp.erase(temp.begin()+table[j]);}res.push_back(medRes);addOne(table, bound);}return res;}};
- LeetCode Permutations I && II
- [LeetCode][I]Permutations II
- leetcode: Permutations I II
- [LeetCode] Permutations I, II
- LeetCode | Permutations I,II
- LeetCode题解:Permutations I and II
- [LeetCode 46 & 47]Permutations I & II
- <LeetCode OJ> 47/46 Permutations (II / I)
- LeetCode 46/47. Permutations i, ii
- [Leetcode] #46#47 Permutations I & II
- 【LeetCode】Permutations && Permutations II
- leetcode: Permutations/Permutations II
- leetcode Permutations & Permutations II
- [Leetcode]Permutations && Permutations II
- Permutations I , II
- Leetcode: Permutations and Permutations II
- leetcode-permutations and permutations II
- Leetcode:Permutations与Permutations II
- 中移动净利下滑 玩不转互联网是主因
- JavaSwing实现树形结构
- Spring不配置视图解析器问题
- 获取系统信息
- php、yii通用globals方法
- LeetCode Permutations I && II
- Jsp中的Application使用
- unity3d 阴影效果图——在制作过程中的注意事项
- CSS的width:100%和width:auto区别
- session-request-page-application的作用域
- sp_who, sp_who2和sp_who3
- [转]错误“AxImp.exe”已退出,代码为 -1163019603。
- How Linkers Use Static Libraries to Resolve References
- Bloom Filter算法