您的位置:首页 > 娱乐 > 八卦 > 代码随想录第28天|回溯算法

代码随想录第28天|回溯算法

2024/10/6 20:34:12 来源:https://blog.csdn.net/qq_45699949/article/details/139795120  浏览:    关键词:代码随想录第28天|回溯算法

491. 非递减子序列

在这里插入图片描述
思路:

  • 不可以排序, 否则会改变元素的顺序
  • 对收获的结果有要求, num.size() >= 2, 且 num[i - 1] < num[i]
  • 需要进行去重, 不能使用排序后的方法去重
  • 每一层可用 unordered_set 去重
  • 组合问题, for 遍历需要标记起始位置

bug:

  • 一定要先判断元素是否重复, 再将元素插入
    请添加图片描述
//正确步骤
if (used.find(nums[i]) != used.end()) {continue;
} else if (res_tem.empty()) { // 重复元素res_tem.push_back(nums[i]);
} else if (res_tem.back() > nums[i]) { // 非递增continue;
} else {res_tem.push_back(nums[i]);
}//错误步骤
//当res_tem为空时, 会将重复元素也添加, 一定需要先判断元素是否有使用
if (res_tem.size() == 0) { res_tem.push_back(nums[i]);
} else if (used.find(nums[i]) != used.end()) { //重复元素continue;
} else if (!(res_tem.back() <= nums[i])) {  //非递增continue;
} else {res_tem.push_back(nums[i]);
}
class Solution {
public:vector<vector<int>> res;vector<int> res_tem;void myoperator(vector<int>& nums, int index) {if (res_tem.size() >= 2) {res.push_back(res_tem);}unordered_set<int> used;for (int i = index; i < nums.size(); i++) {if (used.find(nums[i]) != used.end()) {continue;} else if (res_tem.empty()) { // 重复元素res_tem.push_back(nums[i]);} else if (res_tem.back() > nums[i]) { // 非递增continue;} else {res_tem.push_back(nums[i]);}// 等效操作// if (!res_tem.empty() && nums[i] < res_tem.back()) {//     continue;// }// if (used.find(nums[i]) != used.end()) {//     continue;// }// res_tem.push_back(nums[i]);used.insert(nums[i]);myoperator(nums, i + 1);res_tem.pop_back();}}vector<vector<int>> findSubsequences(vector<int>& nums) {myoperator(nums, 0);return res;}
};

46.全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
在这里插入图片描述
思路:

  • 不能使用index来跳过元素, 因为与顺序有关, 所以遍历从 i = 0 开始
  • 每个元素都要遍历, 可以使用 used 数组去重
  • 无法用 unordered_set 去重, 每层树枝都有相互关联, 不是去除重复数字操作

请添加图片描述

class Solution {
public:vector<vector<int>> res;vector<int> res_tem;vector<bool> uesed;void myoperator(vector<int>& nums) {if (res_tem.size() == nums.size()) {res.push_back(res_tem);return;}for (int i = 0; i < nums.size(); i++) {if (uesed[i] == true) {continue;}uesed[i] = true;res_tem.push_back(nums[i]);myoperator(nums);uesed[i] = false;res_tem.pop_back();}}vector<vector<int>> permute(vector<int>& nums) {uesed = vector<bool>(nums.size(), 0);myoperator(nums);return res;}
};

47. 全排列 II

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列
在这里插入图片描述
请添加图片描述
思路:

  • 取叶子节点, 中间需要去除, 相同数层之间不能用同样的数值
  • 排列则需要从0开始, 使用used标记使用过的元素
class Solution {
public:vector<vector<int>> res;vector<int> res_tem;vector<bool> flag;void myoperator(vector<int>& nums) {if (res_tem.size() == nums.size()) {res.push_back(res_tem);return;}unordered_set<int> used;for (int i = 0; i < nums.size(); i++) {if (used.find(nums[i]) != used.end()) {continue;}if (flag[i] == true) {continue;}flag[i] = true;used.insert(nums[i]);res_tem.push_back(nums[i]);myoperator(nums);flag[i] = false;res_tem.pop_back();}}vector<vector<int>> permuteUnique(vector<int>& nums) {flag = vector<bool>(nums.size(), false);myoperator(nums);return res;}
};

51. N 皇后
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
在这里插入图片描述
参考
请添加图片描述


37. 解数独
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
参考
请添加图片描述