题目描述
知识点
回溯,分治
结果
实现
码前思考
- 首先,对于这道题目而言,它貌似没有考虑字典序的问题,所以就是非常简单的回溯问题,如果考虑了字典序的问题,那就不是简单的回溯遍历问题了!
- 注意:按照字典序排列的全排列只是全排列中的一种,全排列是可以乱序的。
- 我是使用的按照字典序排列的想法来做这道题目的。
- 对于按照字典序排列的全排列,可以使用分治算法来解决,即不断地缩小问题的规模,也就是动态规划里面讲的划分子问题,这里面的体现就是对于每一位枚举可以的数字,枚举完之后直接交给下一位处理,不管了,这就是划分子问题,交给子问题处理,寻找父问题和子问题之间的关系。
代码实现
//经典的全排列问题
class Solution {
private:
vector<bool> hashTable;
vector<vector<int>> res;
vector<int> cur;
public:
vector<vector<int>> permute(vector<int>& nums) {
//首先需要对数组进行一个从小到大的排序
sort(nums.begin(),nums.end());
int size = nums.size();
//初始化hashTable
hashTable.assign(size,false);
//接下来进行全排列
generate(0,nums);
return res;
}
void generate(int idx,vector<int>& nums){
if(idx == nums.size()){ //说明已经得到全排列了
res.push_back(cur);
return;
}else{
//注意这里已经是从小到大排序了
for(int i=0;i<hashTable.size();i++){
if(hashTable[i] == false){
//说明可以进行访问
hashTable[i] = true;
cur.push_back(nums[i]);
generate(idx+1,nums);
cur.pop_back();
hashTable[i] = false;
}
}
}
}
};
码后反思
- 需要使用
HashTable
保存当前可用的数字;
二刷代码
//典型的dfs的题目
class Solution {
public:
vector<bool> vis;
vector<vector<int>> res;
vector<int> path;
int len;
void dfs(int idx,vector<int>& nums){
if(idx==len){
res.push_back(path);
}else{
for(int i=0;i<len;i++){
if(vis[i]==false){
vis[i]=true;
path.push_back(nums[i]);
dfs(idx+1,nums);
path.pop_back();
vis[i]=false;
}
}
}
return;
}
vector<vector<int>> permute(vector<int>& nums) {
len=nums.size();
vis.assign(len,false);
dfs(0,nums);//从第0位开始遍历
return res;
}
};