1 递增子序列
回溯+哈希(有限数据使用used效率更高)
注意:本题不能对其进行排序,这样会破坏原有顺序
used数组
class Solution {
vector<int> path;
vector<vector<int>> result;
private:
void backtracking(vector<int>& nums,int startIndex){
//子集系列不需要终止条件,因为startIndex递增,会超出for循环界限
if(path.size() > 1){
result.push_back(path);//只要子序列超过2个,就将处理后的放入结果集
}
//利用数组used进行树层去重
int used[201] = {0};//每一层都有一个used 范围是-100到100
for(int i = startIndex; i < nums.size(); i++){
if(!path.empty() && nums[i] < path.back() || used[nums[i]+100] == 1) {
continue;
}
used[nums[i]+100] = 1;
path.push_back(nums[i]);
backtracking(nums,i+1);
path.pop_back();
}
}
public:
vector<vector<int>> findSubsequences(vector<int>& nums) {
path.clear();
result.clear();
if(nums.size() == 0) return result;
backtracking(nums,0);
return result;
}
};
set
class Solution {
vector<int> path;
vector<vector<int>> result;
private:
void backtracking(vector<int>& nums,int startIndex){
//子集系列不需要终止条件,因为startIndex递增,会超出for循环界限
if(path.size() >1){
result.push_back(path);//只要子序列超过2个,就将处理后的放入结果集
}
//利用unordered_set进行树层去重
unordered_set<int> uset;//每一层都有一个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) {
path.clear();
result.clear();
if(nums.size() == 0) return result;
backtracking(nums,0);
return result;
}
};
2 全排列
class Solution {
vector<int> path;
vector<vector<int>> result;
private:
//组合问题和子集问题中有startIndex避免出现[1,2]和[2,1]这种情况,而全排列不需要,但是要利用used记录使用过的元素
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] == 0){//此元素没有使用过
path.push_back(nums[i]);
used[i] = 1;
backtracking(nums,used);
used[i] = 0;
path.pop_back();
}else continue;
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
if(nums.size() == 0) return result;
vector<bool> used(nums.size(),false);//标记取过哪些元素,接下来取过的元素不能重复取,但是前面的元素还可以取
backtracking(nums,used);
return result;
}
};
3 全排列Ⅱ
class Solution {
vector<int> path;
vector<vector<int>> result;
private:
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 && used[i-1] == 0 && nums[i] == nums[i-1]) continue;//used[i-1]==0说明是树层上去重
if(used[i] == 0){//此元素没有使用过
path.push_back(nums[i]);
used[i] = 1;
backtracking(nums,used);
used[i] = 0;
path.pop_back();
}
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
if(nums.size() == 0) return result;
vector<bool> used(nums.size(),false);//标记取过哪些元素,接下来取过的元素不能重复取,但是前面的元素还可以取
sort(nums.begin(),nums.end());//排序才能将一样的数放在一起
backtracking(nums,used);
return result;
}
};