491.递增子序列
1.自己的回溯
这道题目和集合类似,是所有节点都需要处理。
这道题目数组不能排序,所以去重比较麻烦,需要和本层所有用过的数字比较。
vector<vector<int>> res;
vector<int> path;
void backtracing(vector<int>& nums, int startIndex)
{
if (path.size() >= 2)
res.push_back(path);
if (startIndex >= nums.size()) return;
for (int i = startIndex; i < nums.size(); i++)
{
if (!path.empty() && nums[i] < path.back())
continue;
if (i > startIndex)
{
int j;
for (j = startIndex; j < i; j++)
{
if (nums[j] == nums[i]) break;
}
if (j < i) continue;
}
path.push_back(nums[i]);
backtracing(nums, i + 1);
path.pop_back();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
res.clear();
path.clear();
if (nums.empty()) return res;
backtracing(nums, 0);
return res;
}
2.一种优化的去重思路
可以用unodered_set或者哈希的方法,记录那些用过的数字
两者中哈希更好,因为快,这道题中只需要用数组就可以哈希,因为其范围只有201
set做法如下:
unordered_set<int> uset;
for (int i = startIndex; i < nums.size(); i++)
{
//...
if (i > startIndex && uset.find(nums[i]) != uset.end())
continue;
uset.insert(nums[i]);
//...
}
哈希的做法如下:
bool used[201] = {false};
for (int i = startIndex; i < nums.size(); i++)
{
//...
if (i > startIndex && used[nums[i] + 100] == true)
continue;
used[nums[i] + 100] = true;
//...
}
46.全排列
进入到回溯第四类问题——排列!
排列没办法,必须要用used记录是否用过了,startIndex用不了啦
used表示的是从纵向记录,也就是是否在树枝上已经用过。
vector<vector<int>> res;
vector<int> path;
void backtracing(vector<int>& nums, vector<bool>& used)
{
if (path.size() == nums.size())
{
res.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++)
{
if (used[i] == false)
{
used[i] = true;
path.push_back(nums[i]);
backtracing(nums, used);
path.pop_back();
used[i] = false;
}
else
continue;
}
}
vector<vector<int>> permute(vector<int>& nums) {
res.clear();
path.clear();
vector<bool> used;
for (int i = 0; i < nums.size(); i++)
used.push_back(false);
backtracing(nums, used);
return res;
}
47.全排列 II
这题就是nums中有重复数字,做一个去重就可以
这里去重有一个小细节就是,只有前一位是没用过的情况下,重复才跳过。和以前组合那一样,因为涉及到范围,用过的话自然就不在可选范围。
vector<vector<int>> res;
vector<int> path;
void backtracing(vector<int>& nums, vector<bool>& used)
{
if (path.size() == nums.size())
{
res.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++)
{
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false)
continue;
if (used[i] == true)
continue;
used[i] = true;
path.push_back(nums[i]);
backtracing(nums, used);
path.pop_back();
used[i] = false;
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
res.clear();
path.clear();
vector<bool> used(nums.size(), false);
sort(nums.begin(), nums.end());
backtracing(nums, used);
return res;
}