LeetCode/全排列
给定一个不含重复数字的数组nums,返回其所有可能的全排列,你可以按任意顺序返回答案
1. 不含重复元素排列(回溯法)
每次选一个,转移到下一空间,考虑用回溯思想
遍历选取当前可选数,递归每一位,当最后一位选取结束时记录结果
class Solution {
public:
vector<vector<int>> res;
vector<vector<int>> permute(vector<int>& nums) {
vector<int> num;
backtrack(nums,num);
return res;
}
void backtrack(vector<int>& nums,vector<int>& num)
{
if(num.size()==nums.size()){
res.push_back(num);
return;
}
for(int i=0;i<nums.size();i++)
{
if(count(num.begin(),num.end(),nums[i])) continue;
num.push_back(nums[i]);
backtrack(nums,num);
num.pop_back();
}
}
};
通过交换不占空间
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int> > res;
backtrack(res, nums, 0, (int)nums.size());
return res;
}
void backtrack(vector<vector<int>>& res, vector<int>& output, int first, int len){
// 所有数都填完了
if (first == len) {
res.emplace_back(output);
return;
}
for (int i = first; i < len; ++i) {
// 动态维护数组
swap(output[i], output[first]);
// 继续递归填下一个数
backtrack(res, output, first + 1, len);
// 撤销操作
swap(output[i], output[first]);
}
}
};
2. 有重复元素排列
class Solution {
vector<vector<int>> res;
vector<int> temp;
vector<int> vis;
public:
void backtrack(vector<int>& nums, int index) {
if (index == nums.size()) {
res.push_back(temp);
return;
}
for (int i=0;i<nums.size();++i) {//每位遍历每个数
//(1122333444)
//如果此数已在待定数组,跳过选择其他数(每个数只能用一次)
//与前一个数相同,且前一数不在待定数组,说明该位此数已被递归过,跳过
//与前一个数相同,但前一数在待定数组,说明该位此数没被递归过
if (vis[i] || (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1]))
continue;
temp.push_back(nums[i]);//选择
vis[i] = 1;//表示该位已访问过
backtrack(nums,index + 1);//递归到下一位
vis[i] = 0;
temp.pop_back();//撤回
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vis.resize(nums.size());
sort(nums.begin(), nums.end());//排序
backtrack(nums, 0);
return res;
}
};
3. 拓展(下一个排列)
给定一个排列,求下一个字典序更大的排列
下一个排列
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int i = nums.size() - 2;//从倒数第二个位置开始,防止比较时溢出
while (i >= 0 && nums[i] >= nums[i + 1])
i--;//从后往前找第一对升序对
if (i >= 0) {
int j = nums.size() - 1;//从倒数第一个位置开始
while (j >= 0 && nums[i] >= nums[j]) //找第一个比索引i大的数
j--;
swap(nums[i], nums[j]);//将两个数交换
}
reverse(nums.begin() + i + 1, nums.end());//反转i后面的数(如果没找到升序对全部反转)
}
};