491 递增子序列
思路:这道题可以使用回溯算法来解决,回溯算法在深度优先搜索的基础上增加了撤销选择的步骤。
我们使用一个变量 start 表示搜索的起始位置,遍历 nums[start:] 中的元素,如果当前元素大于等于已选择的元素中的最后一个元素,则将其添加到已选择的元素中,并递归搜索 start+1 开始的位置,搜索完成后需要将选择的元素列表中的最后一个元素弹出,从而实现撤销选择的操作。
在递归过程中,如果已选择的元素个数大于等于 2,就将其加入到结果集中,这样就能够得到所有不同的递增子序列。
需要注意的是,为了避免重复的子序列,我们需要使用一个集合来存储已经搜索过的序列。在搜索过程中,如果当前的序列已经在集合中出现过了,就不需要再搜索下去了。
1.回溯
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);
unordered_set<int> uset;
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) {
backtracking(nums, 0);
return result;
}
};
46 全排列
思路:定义一个私有变量 result 保存最终的结果,定义一个私有变量 path 保存当前的排列。
1.定义一个私有函数 backtracking,参数为当前的输入数组 nums 和一个布尔型数组 used,用于标记哪些元素已经被选择过了。
2.如果当前的排列长度等于输入数组的长度,则将当前排列加入到结果集中,并返回。
3.遍历输入数组,如果当前元素已经被选择过了,则跳过这个元素;否则,将这个元素添加到当前的排列中,并标记为已选择。
4.递归调用 backtracking 函数,搜索下一个位置的元素。
5.回溯操作,将当前元素从排列中弹出,并将其标记为未选择。
6.最后,定义一个公有函数 permute,初始化布尔型数组 used,然后调用 backtracking 函数进行搜索,最后返回结果集。
1.回溯
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(used[i] == true) continue;
path.push_back(nums[i]);
used[i] = true;
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};
47 全排列 II
思路:这道题与上一题的区别在于输入数组中可能包含重复元素。因此,在搜索过程中需要去重。
具体方法是在每次递归调用 backtracking 函数之前,先对输入数组进行排序,然后在搜索时跳过重复元素。
另外,在搜索结束后,需要将当前的排列加入到结果集中之前,再检查一遍结果集中是否已经存在相同的排列,避免结果集中出现重复的排列。
1.回溯
class Solution {
private:
vector<int> path;
vector<vector<int>> result;
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] && used[i - 1] == false) continue;
if(used[i] == false){
path.push_back(nums[i]);
used[i] = true;
backtracking(nums, used);
used[i] = false;
path.pop_back();
}
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<bool> used(nums.size(), false);
backtracking(nums, used);
return result;
}
};