491. 递增子序列 - 力扣(LeetCode)
思路:
- 使用回溯法,若
path.size() >= 2
则将其加入答案,因为本题给的数组中可能含有重复元素,但是又不能进行排序,所以我们采用set
来去除同一树层中重复的的元素,在进行判断的时候,因为涉及到当前选中元素和path
中最后一个元素对比,所以需要判断path.empty() || nums[i] >= path[path.size() - 1]
是否为真,若为真则进行下一层递归,记得要回溯
我的AC代码
使用set去重
class Solution {
public:
vector<vector<int>> ans;
vector<int> path;
void backtracking(vector<int>& nums, int cur) {
if(path.size() >= 2) {
ans.push_back(path);
}
unordered_set<int> set;
for(int i = cur; i < nums.size(); ++i) {
if(set.find(nums[i]) != set.end()) {
continue;
}
else if(path.empty() || nums[i] >= path[path.size() - 1]) {
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
set.insert(nums[i]);
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
backtracking(nums, 0);
return ans;
}
};
标准答案
使用set去重
// 版本一
class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int startIndex) {
if (path.size() > 1) {
result.push_back(path);
// 注意这里不要加return,要取树上的节点
}
unordered_set<int> uset; // 使用set对本层元素进行去重
for (int i = startIndex; i < nums.size(); i++) {
if ((!path.empty() && nums[i] < path.back())
|| uset.find(nums[i]) != uset.end()) {
continue;
}
uset.insert(nums[i]); // 记录这个元素在本层用过了,本层后面不能再用了
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
result.clear();
path.clear();
backtracking(nums, 0);
return result;
}
};
使用数组去重
// 因为本题数值范围[-100,100]
// 所以其实用数组来做哈希,效率会高很多
// 程序运行的时候对unordered_set 频繁的insert,unordered_set需要做哈希映射(也就是把key通过hash function映射为唯一的哈希值)相对费时间,而且每次重新定义set,insert的时候其底层的符号表也要做相应的扩充,也是费事的。
// 版本二
class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int startIndex) {
if (path.size() > 1) {
result.push_back(path);
}
int used[201] = {0}; // 这里使用数组来进行去重操作,题目说数值范围[-100, 100]
for (int i = startIndex; i < nums.size(); i++) {
if ((!path.empty() && nums[i] < path.back())
|| used[nums[i] + 100] == 1) {
continue;
}
used[nums[i] + 100] = 1; // 记录这个元素在本层用过了,本层后面不能再用了
path.push_back(nums[i]);
backtracking(nums, i + 1);
path.pop_back();
}
}
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
result.clear();
path.clear();
backtracking(nums, 0);
return result;
}
};
46. 全排列 - 力扣(LeetCode)
思路:
- 使用回溯法,每一层递归的循环都从头开始,使用
used
数组来标记该数字是否已被加入path
,若已加入,则跳过,否则进入下一层循环,要记得回溯
我的AC代码
class Solution {
public:
vector<vector<int>> ans;
vector<int> path;
void backtracking(vector<int>& nums, vector<int>& used) {
if(path.size() > nums.size()) {
return;
}
else if(path.size() == nums.size()) {
ans.push_back(path);
}
for(int i = 0; i < nums.size(); ++i) {
if(used[i] == 1) {
continue;
}
else {
path.push_back(nums[i]);
used[i] = 1;
backtracking(nums, used);
used[i] = 0;
path.pop_back();
}
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<int> used(nums.size(), 0);
backtracking(nums, used);
return ans;
}
};
标准答案
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking (vector<int>& nums, 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) continue; // path里已经收录的元素,直接跳过
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
result.clear();
path.clear();
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};
47. 全排列 II - 力扣(LeetCode)
思路:
- 本题使用回溯法,用数组来进行树层去重,使用used来记录已被选取过的数字
我的AC代码
class Solution {
public:
vector<vector<int>> ans;
vector<int> path;
void backtracking(vector<int>& nums, vector<int>& used) {
if(path.size() == nums.size()) {
ans.push_back(path);
return;
}
int re[20] = {0};
for(int i = 0 ; i < nums.size(); ++i) {
if(used[i] == 1 || re[nums[i] + 10] == 1) {
continue;
}
else {
used[i] = 1;
path.push_back(nums[i]);
backtracking(nums, used);
used[i] = 0;
path.pop_back();
}
re[nums[i] + 10] = 1;
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<int> used(nums.size(), 0);
backtracking(nums, used);
return ans;
}
};
标准答案
class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void backtracking (vector<int>& nums, vector<bool>& used) {
// 此时说明找到了一组
if (path.size() == nums.size()) {
result.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++) {
// used[i - 1] == true,说明同一树枝nums[i - 1]使用过
// used[i - 1] == false,说明同一树层nums[i - 1]使用过
// 如果同一树层nums[i - 1]使用过则直接跳过
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
continue;
}
if (used[i] == false) {
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
result.clear();
path.clear();
sort(nums.begin(), nums.end()); // 排序
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};
Comments NOTHING