491.递增子序列
题目链接:491.递增子序列,难度:中等
【实现代码】
class Solution {
private:
vector<vector<int>> result;
vector<int> path;
void backTracking(vector<int>& nums, int startIndex) {
if (path.size() >= 2) {
result.push_back(path);
}
int used[201] = {0};
for (int i = startIndex; i < nums.size(); i++) {
// cout << i << " ";
if ((!path.empty() && nums[i] < path.back()) || used[nums[i] + 100] == 1) {
continue;
}
path.push_back(nums[i]);
used[nums[i] + 100] = 1;
backTracking(nums, i + 1);
path.pop_back();
}
// cout << endl;
}
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
backTracking(nums, 0);
return result;
}
};
【解题思路】
子集问题使用回溯算法解决。
回溯三步曲:
- 确定函数参数:原数组和开始索引
- 确定结束条件:当path的长度大于2时就结束
- 单层逻辑:当前元素大于数组尾值时,且没有使用过就存入path,然后就行下一个递归。本题目的去重是树层去重。
46.全排列
题目链接:46.全排列,难度:中等
【实现代码】
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++) {
if (false == used[i]) {
path.push_back(nums[i]);
used[i] = true;
backTracking(nums, used);
path.pop_back();
used[i] = 0;
}
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> used(nums.size(), false);
backTracking(nums, used);
return result;
}
};
【解题思路】
排列问题使用回溯算法解决。
回溯三步曲:
- 确定函数参数:原数组和used数组,因为排列有顺序区分,所以每一层都是从0开始循环
- 确定结束条件:当path的长度等于原数组的长度,就结束
- 单层逻辑:如果当前元素没有使用过就存入path,然后进行下一个递归。
47.全排列II
题目链接:47.全排列II,难度:中等
【实现代码】
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++) {
if ((i > 0 && nums[i] == nums[i - 1]) && false == used[i - 1]) {
continue;
}
if (true == used[i]) {
continue;
}
// cout << i << " ";
path.push_back(nums[i]);
used[i] = true;
backTracking(nums, used);
path.pop_back();
used[i] = false;
}
// cout << endl;
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<bool> used(nums.size(), false);
backTracking(nums, used);
return result;
}
};
【解题思路】
本题目和上一题类似,难点在于去重。
回溯三步曲:
- 确定函数参数:原数组和used数组
- 确定结束条件:当path数组的长度等于原数组的长度时就结束
- 单层逻辑:首先就是树层去重,当前元素和前一个元素相等时,used对应下标的值为false,则前一个元素已经使用过,跳过当前元素;接着是跳过已经使用的元素,即在一个树枝中,used对应下标的值为true,即使用过,最后存入path,进行下一个递归。
文章介绍了如何使用回溯算法解决491.递增子序列、46.全排列和47.全排列II这三道编程题目。回溯法在每一步选择中都尽可能深地进入搜索树,并在达到预设条件时返回。对于全排列问题,关键在于处理排列的顺序和去重策略。
510

被折叠的 条评论
为什么被折叠?



