数字排列问题 (三种解法)
最简单的数字全排列模板问题:Permutations
本文主讲题目:Permutations II
题目:输入一组数字(可能包含重复数字),输出其所有的排列方式。
思路:保持原数组的相同的数位置保持“不变”(只能在其身后插入), 即将原数组先排序, //
随后答案路径数组中选择位置依次插入原数组的所有数字,直到插入完毕
法一:
这里bool数组(st)进行判断, start的刷新为下一位置存放
代码如下:
class Solution {
public:
//思路:保持原数组的相同的数位置保持“不变”(只能在其身后插入), 即将原数组先排序,
// 随后答案路径数组中选择位置插入原数组的每个数字,直到插入完毕
vector<bool> st;
vector<int> path;
vector<vector<int>> res;
vector<vector<int>> permutation(vector<int>& nums) {
st = vector<bool>(nums.size(), false);
sort(nums.begin(), nums.end());
path = vector<int>(nums.size());
dfs(nums, 0, 0);
return res;
}
void dfs(vector<int> &nums, int u, int start) {
if(u == nums.size()) { //代表遍历放完数组所有的数
res.push_back(path);
return ;
}
for(int i = start; i < nums.size(); i++) { //从start开始遍历后面的path位置
if(!st[i]) {
st[i] = true;
path[i] = nums[u];
//后一个数与当前数不相同,那么位置随意挑, 即可以从第一个位置开始遍历
if(nums[u] != nums[u + 1] && u + 1 < nums.size())
dfs(nums, u + 1, 0);
else //相同的话那么只能放在path当前位置
dfs(nums, u + 1, i + 1); 的后面
st[i] = false;
}
}
}
};
法二:
这里为了省空间, 用二进制的一个数的各位置为0或1表示当前位置是否被使用, 因为是数, 不是全局的数组, 所以也省去了"恢复"的操作
代码如下:
class Solution {
public:
//思路:保持原数组的相同的数位置保持“不变”(只能在其身后插入), 即将原数组先排序,
// 随后答案路径数组中选择位置插入原数组的每个数字,直到插入完毕
// vector<bool> st;
vector<int> path;
vector<vector<int>> res;
vector<vector<int>> permutation(vector<int>& nums) {
sort(nums.begin(), nums.end());
path = vector<int>(nums.size());
dfs(nums, 0, 0, 0);
return res;
}
void dfs(vector<int> &nums, int u, int start, int state) {
if(u == nums.size()) { //代表遍历放完数组所有的数
res.push_back(path);
return ;
}
if(!u || nums[u] != nums[u - 1]) start = 0;
for(int i = start; i < nums.size(); i++) {
if(!(state >> i & 1)) {
path[i] = nums[u];
//第四个位置(state)意思为:当前位置数字已经被加载使用
dfs(nums, u + 1, i + 1, state + (1 << i));
//这里不需要恢复操作了, 因为进行判断的是数, 自动恢复
}
}
}
};
法三:
可以直接使用stl自带的库函数:next_permutation
next_permutation
是一个原地算法(会直接改变这个集合,而不是返回一个集合),它对一 个可以遍历的集合(如string,如vector),将迭代器范围
[first, last] 的排列
排列到 下一个排列(第一个是名词,第二个是动词,第三个是名词),其中所有排列的集合默认按照 operator < 或者 字典序 或者
按照输入到第三个参数 comp 的排列方法排列。如果存在这样 的“下一个排列”,返回true
并执行排列,否则返回false
。
代码如下:
class Solution {
public:
vector<vector<int>> permutation(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
do{
res.push_back(nums);
}while(next_permutation(nums.begin(), nums.end()));
return res;
}
};