全排列1
全排列是经典必背题目,主要用回溯的办法,应用used数组来记录元素是否已经被遍历过,直接记录代码即可:
class Solution {
vector<int> path;
vector<vector<int>> re;
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> used(nums.size(), false);
trace(nums, used);
return re;
}
void trace(vector<int> &num, vector<bool>& used)
{
//递归结束条件
if(path.size() == num.size())
{
re.push_back(path);
return;
}
//递归 每次都要看全部的数组
for(int i = 0; i < num.size(); ++i)
{
if(used[i])//注意这里,如果用过则跳过这个元素
{
continue;
}
else
{
used[i] = true;
path.push_back(num[i]);//进入现场
trace(num, used);
path.pop_back();//恢复现场
used[i] = false;
}
}
}
};
全排列2
全排列2和全排列1的区别在于,数组是包含可重复数字的,而且还不一定是有序的。
所以在全排列1的基础上,增加两个东西:
(1)数组排序,目的是为了给(2)的剪枝用。
(2)增加剪枝,除了used[i]数组来标记外,还需要去重复数字带来的影响。如果num[i] == num[i - 1] && used[i - 1] == 1,也就是如果这个数组和前一个相同,而且前一个已经被用了,那么跳过这个组合。
代码记录一下:
#include <algorithm>
class Solution {
public:
vector<vector<int>> result;
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());//排序一下,以保证相同的数字挨在一起(1)
vector<int> path;
vector<bool> used(nums.size(), false);
trace(nums, path, used);
return result;
}
void trace(vector<int> &nums, vector<int> path, vector<bool> &used)
{
if(path.size() == nums.size())
{
result.push_back(path);
return;
}
for(int i = 0; i < nums.size(); ++i)
{
if(used[i] == true || (i != 0 && used[i - 1] == true && nums[i] == nums[i - 1]))//注意剪枝,重点在这里(2)
{
continue;
}
used[i] = true;
path.push_back(nums[i]);
trace(nums, path, used);
path.pop_back();
used[i] = false;
}
return;
}
};