[LeetCode]Permutations II(!!!!!DFS递归&&回溯)
2015-07-19 15:26
453 查看
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].
生成给定数字的全排列,这里给定数字中有重复数字,所以在相邻的重复数字中,我们只递归第一个遇到的未访问的数字。
可以以11112为例
下标为01234
第0层递归为1
第一层时再传1 ,一直递归直至11112出现
在第一层递归传nums[2],这是nums[1]未访问,所以nums[2]被跳过,接着num[3]也被跳过,传入nums[4],直至12111出现
实际上这种处理方式更容易理解
对于当前permutation,后面这这个元素相同的元素我们都可以pass掉,就是说在递归的出口处处理
两种情况AC都是40ms
另外一种思路是利用Next permutations的思路初始的是最小的数,然后每次寻找它的next permutation
寻找的思路,
以1243为例,先后往前找第一个非递增的数,这里找到nums[1]=2,如果找到为nums[-1]则结束。否则再从后往前找第一个比2大的数,这里为nums[3]=3。交换nums[1]和nums[3],变成1342,从下标为2开始翻转后面的数变成1324
all possible unique permutations.
For example, [1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1].
生成给定数字的全排列,这里给定数字中有重复数字,所以在相邻的重复数字中,我们只递归第一个遇到的未访问的数字。
可以以11112为例
下标为01234
第0层递归为1
第一层时再传1 ,一直递归直至11112出现
在第一层递归传nums[2],这是nums[1]未访问,所以nums[2]被跳过,接着num[3]也被跳过,传入nums[4],直至12111出现
class Solution { public: vector<vector<int>> permuteUnique(vector<int>& nums) { sort(nums.begin(),nums.end()); vector<vector<int>> permus; if(nums.size()<1) return permus; vector<bool> visited(nums.size(),false); //初始都未访问过 vector<int> curr; permu_all(permus,visited,curr,nums); return permus; } void permu_all(vector<vector<int>>& permus, vector<bool>& visited, vector<int> curr, vector<int>& nums){ if(curr.size()==nums.size()){ permus.push_back(curr); return; } for(int i = 0; i < nums.size(); ++i){ if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]) continue; if(visited[i]==false){ visited[i] = true; curr.push_back(nums[i]); permu_all(permus, visited, curr, nums); curr.pop_back(); visited[i]=false; } } } };
实际上这种处理方式更容易理解
对于当前permutation,后面这这个元素相同的元素我们都可以pass掉,就是说在递归的出口处处理
class Solution { public: vector<vector<int>> permuteUnique(vector<int>& nums) { sort(nums.begin(),nums.end()); vector<vector<int>> permus; if(nums.size()<1) return permus; vector<bool> visited(nums.size(),false); //初始都未访问过 vector<int> curr; permu_all(permus,visited,curr,nums); return permus; } void permu_all(vector<vector<int>>& permus, vector<bool>& visited, vector<int> curr, vector<int>& nums){ if(curr.size()==nums.size()){ permus.push_back(curr); return; } for(int i = 0; i < nums.size(); ++i){ //if(i>0&&nums[i]==nums[i-1]&&!visited[i-1]) continue; if(visited[i]==false){ visited[i] = true; curr.push_back(nums[i]); permu_all(permus, visited, curr, nums); curr.pop_back(); visited[i]=false; while(i<nums.size()&&nums[i]==nums[i+1]) ++i; } } } };
两种情况AC都是40ms
另外一种思路是利用Next permutations的思路初始的是最小的数,然后每次寻找它的next permutation
寻找的思路,
以1243为例,先后往前找第一个非递增的数,这里找到nums[1]=2,如果找到为nums[-1]则结束。否则再从后往前找第一个比2大的数,这里为nums[3]=3。交换nums[1]和nums[3],变成1342,从下标为2开始翻转后面的数变成1324
class Solution { public: vector<vector<int>> permuteUnique(vector<int>& nums) { sort(nums.begin(),nums.end()); vector<vector<int>> permus(1,nums); int i,j; while(1){ for(i = nums.size()-1; i >0; --i){ //和i前面的数比 if(nums[i]>nums[i-1]) break; //第一个非升序的数 } if(i==0) break; //找到最大的数了 for(j = nums.size()-1; j>=i; --j){ if(nums[j]>nums[i-1]) break; } swap(nums[i-1],nums[j]); reverse(nums.begin()+i,nums.end()); //reverse(nums,i); permus.push_back(nums); } return permus; } void swap(int &a, int &b){ a=a^b; b=a^b; a=a^b; } /* void reverse(vector<int> &v, int index){ int l =index; int r = v.size()-1; while(l<r){ swap(v[l++],v[r--]); } }*/ };
相关文章推荐
- Apache的prefork模式和worker模式
- html5实现带提示文字的输入框(摆脱js)
- 数据表
- Hadoop Counter
- 2015/7/19 Django学习之入门
- Git基础---Git常用命令
- [Android]The connection to adb is down, and a severe error has occured.
- java创建二叉树并实现非递归中序遍历二叉树
- VS2012如何创建模板
- 学习MongoDB 七: MongoDB索引(索引基本操作)(一)
- dos格式转变为unix格式 总结
- C++中的unique(),unique_copy()的用法
- Zend Studio实用快捷键一览表
- cookies的存值问题
- Spring自动装配
- 字符串排序
- [LeetCode]Contains Duplicate II
- MongoDB_3.0.4在WIN7下的安装与配置
- JAVA中正则表达式总结
- 高性能IO设计的Reactor和Proactor模式