一、LeetCode 491.递增子序列
题目链接:491.递增子序列
题目要求找出并返回所有该数组中不同的递增子序列,且所给的数组中的元素是可能重复的。
那么在使用递归和回溯来寻找时,我们要进行树层上的去重操作(树枝上并不需要去重),我们可以创建一个不可重复的哈希表set来标记树层上每个元素是否出现过,然后实现去重。
而且因为递增子序列中至少有两个元素,所以我们在路径数组的大小大于1的时候才能收集有效子集。
代码如下:
class Solution {
private:
vector<vector<int>>result;
vector<int>path;
public:
void backtraving(vector<int>& nums, int startx) {
if(path.size() > 1) result.push_back(path);
unordered_set<int>set;//记录每个元素在本树层上是否出现过
for (int i = startx; i < nums.size(); i++) {
if(set.find(nums[i]) != set.end() || (path.size() != 0 && nums[i] < path.back())) continue;//如果当前元素在本树层上出现过或者,当前元素小于路径上最后的元素,则直接跳过本层循环
set.insert(nums[i]);//否则记录当前元素在本树层上出现过,然后将其放入路径当中,在递归和回溯
path.push_back(nums[i]);
backtraving(nums, i + 1);
path.pop_back();
}
return;
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
backtraving(nums, 0);
return result;
}
};
二、LeetCode46.全排列
题目链接:46.全排列
这道题如果懂得树枝去重还是比较简单的。
因为题目说明给出的序列是无重复的,所以可以创建一个set哈希表来标记当前所遍历的元素是否在树枝上出现过。
代码如下:
class Solution {
vector<vector<int>>result;
vector<int>path;
unordered_set<int>set;//利用一个哈希表来记录当前元素是否在树枝上出现过
public:
void backtraving(vector<int>& nums) {
if(path.size() == nums.size()) {//递归结束条件:如果路径上的元素个数等于原数组大小,说明得到一个全排列,将其收集在结果集里
result.push_back(path);
return;
}
for(int i = 0; i < nums.size(); i++) {
if(set.find(nums[i]) != set.end()) continue;//如果当前元素在当前树枝上出现过,则跳过这层循环
path.push_back(nums[i]);//否则将其放入路径上然后标记下来,再递归和回溯
set.insert(nums[i]);
backtraving(nums);
path.pop_back();
set.erase(nums[i]);
}
return;
}
vector<vector<int>> permute(vector<int>& nums) {
backtraving(nums);
return result;
}
};
三、LeetCode47.全排列 II
题目链接:47.全排列 II
这道题需要用树层去重和树枝去重。
当然首先需要对数组进行排序,以便更好的去重。
每遍历到一个树是先判断其是否在数层上出现过,如果出现过跳过循环。
然后再判断其是否再树枝上出现过,如果没出现则可以继续递归(同时将其标记成在树枝上出现过)。
以下是代码:
class Solution {
vector<vector<int>>result;
vector<int>path;
public:
void backtraving(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;
backtraving(nums, used);
used[i] = false;
path.pop_back();
}
}
return;
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<bool>used(nums.size(),false);//用布尔数组对每个数是否在树层和树枝上出现过做标记
backtraving(nums, used);
return result;
}
};
总结
以上就是今天的内容。