78. 子集
这道题和前几题有些不一样,前几题都是有条件的收集路径path。比如对路径path的大小加一限制,或者对路径path的和加以限制。但是在这道题中对路径path没有任何限制,只需要我们在取出一个值后,将值输入result中,再从剩余元素中取一值,不断递归回溯。
class Solution {
private:
vector> result;
vector path;
void backtracking(vector nums,int startIndex)
{
//将path赋值给result时不需要加任何限制
result.push_back(path);
//每个for循环都是在遍历同一层
for(int i=startIndex;i> subsets(vector& nums) {
backtracking(nums, 0);
return result;
}
};
90. 子集 II
这道题和力扣第40题类似,都需要对数组进行排序后,修剪掉同层的相同元素,保证组合不重复。 那什么时候是在遍历同层元素呢?当i>startIndex时就是在遍历同层元素。可以看看我上篇文章第40题的解析,可以了解到什么在遍历同层、什么时候在遍历同枝。
class Solution {
public:
vector path;
vector> ans;
void backtracking(vector nums,int startIndex)
{
ans.push_back(path);
for(int i=startIndex;istartIndex && nums[i]==nums[i-1]) continue;
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
vector> subsetsWithDup(vector& nums) {
sort(nums.begin(),nums.end());
backtracking(nums,0);
return ans;
}
};
491. 递增子序列
这题也是从集合中不断取值,题目要求结果不能出现重复的集合,所以要进行去重操作。但是这题的去重和前几题又有一些不同,前面都是可以先排序然后再去重。这题要求返回子序列,排序后子序列就改变了,所以不能排序。需要同层去重,如果我们可以记录同一层中哪些元素已经使用过了,然后再遍历新的元素时查看该元素的值是否被使用过。那么问题就解决了。
于是我们用一个集合来记录哪些元素已经使用过了
class Solution {
public:
vector path;
vector> ans;
void backtracking(vector nums,int startIndex)
{
if(path.size()>=2)
ans.push_back(path);
unordered_set used;//创建一个集合来存放一些已经使用过的值
for(int i=startIndex;i0 && nums[i]> findSubsequences(vector& nums) {
backtracking(nums,0);
return ans;
}
};
!!!错误代码
class Solution {
public:
vector path;
vector> ans;
unordered_set used;
void backtracking(vector nums,int startIndex)
{
if(path.size()>=2)
ans.push_back(path);
used.clear();//used设为全局变量导致这里清空的话,那上一层的记录也全部被清空了,used变量将毫无作用,等于没写
for(int i=startIndex;i0 && nums[i]> findSubsequences(vector& nums) {
backtracking(nums,0);
return ans;
}
};
46. 全排列
这道题是排列,排列和组合不一样。排列有序,组合无序。比较简单的思路就是当取出一个元素后,我们就将这个元素移除,然后再剩余的元素中再取值,直到没有剩余的元素了。
class Solution {
public:
vector path;
vector> ans;
void backtracking(vector nums)
{
if(nums.empty())
{
ans.push_back(path);
return;
}
for(int i=0;i temp=nums;
temp.erase(temp.begin()+i);
backtracking(temp);
path.pop_back();
}
}
vector> permute(vector& nums) {
backtracking(nums);
return ans;
}
};
第二种方法是用一个数组来记录已经已经使用过的元素
class Solution {
public:
vector path;
vector> ans;
void backtracking(vector nums,vector used)
{
if(path.size()==nums.size())
{
ans.push_back(path);
return;
}
for(int i=0;i> permute(vector& nums) {
vector used(nums.size(),false);
backtracking(nums,used);
return ans;
}
};
47. 全排列 II
相较于上一题,这题多了一步去重的操作。我们可以在排序后直接用used进行同层去重,和之前的题目一样,如果前一个元素的used值为false,说明两个元素处于同层。
class Solution {
public:
vector path;
vector> ans;
void backtracking(vector nums,vector used)
{
if(path.size()==nums.size())
{
ans.push_back(path);
return;
}
for(int i=0;i0 && used[i-1]==false && nums[i]==nums[i-1]) continue;
//这个是对自己进行去重,防止再取到自己
if(used[i]==true) continue;
path.push_back(nums[i]);
//标记使用过的元素
used[i]=true;
backtracking(nums,used);
path.pop_back();
used[i]=false;
}
}
vector> permuteUnique(vector& nums) {
sort(nums.begin(),nums.end());
vector used(nums.size(),false);
backtracking(nums,used);
return ans;
}
};