主要思路:
因为数据范围比较小,所以可以开一个数组,每轮递归利用这个数组记录元素是否使用过,如果使用过,就可以像40. 组合总和 II这题一样剪枝减掉,因为重复的话前面肯定就会遍历过所有可能了,但本题一个陷阱就是不能先对原数组排序,所以如果发现循环遍历的元素小于最后压入path的元素,就说明不能构成递增,就continue
易错点:
(1)如何处理重复元素:如果想用数组下标记录元素,一定要+100,否则下标无法表示负数
(2)如何保证path里递增
代码实现:
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}; // 这里使用数组来进行去重操作,题目说数值范围[-100, 100]
for (int i = startIndex; i < nums.size(); i++) {
//将nums[i]与最后压入path的比较实现path内递增,妙啊
if ((!path.empty() && nums[i] < path.back())
|| used[nums[i] + 100] == 1) { //咳咳,这里其实是ACM常见技巧,num[i] + 100相当于移动范围,从-100~100到0~200,由哈希表一一映射可知结果不变
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) {
result.clear();
path.clear();
backtracking(nums, 0);
return result;
}
};
主要思路:
上一题其实就相当于这一题的预热,也要用一个数组记录当前遍历的元素是否使用过,不同的是该数组设在全局变量里,且要有相应回溯
代码实现:
class Solution {
public:
vector<vector<int>>result;
vector<int>path;
int used[21];
void backtracking(vector<int>& nums) {
if(path.size() == nums.size()) {
result.push_back(path);
return;
}
for(int i = 0; i < nums.size(); i++) {
int tmp = nums[i] + 10;
if(used[tmp] == 1) continue;
else used[tmp] = 1;
path.push_back(nums[i]);
backtracking(nums);
used[tmp] = 0;
path.pop_back();
}
return;
}
vector<vector<int>> permute(vector<int>& nums) {
backtracking(nums);
return result;
}
};
第一次写错误
(1)忘记有负数平移范围了
主要思路:
因为有重复元素,所以不仅有树枝去重,还有树层去重
代码实现:
class Solution {
public:
vector<vector<int>>result;
vector<int>path;
int branchUsed[10];
void backtracking(vector<int>& nums) {
if(path.size() == nums.size()) {
result.push_back(path);
return;
}
int layerUsed[21] = {0};
for(int i = 0; i < nums.size(); i++) {
int tmp = nums[i] + 10;
if(layerUsed[tmp] == 1 || branchUsed[i] == 1) continue; //先树层去重,在树枝去重
branchUsed[i] = 1;
layerUsed[tmp] = 1;
path.push_back(nums[i]);
backtracking(nums);
branchUsed[i] = 0;
path.pop_back();
}
return;
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
backtracking(nums);
return result;
}
};
第一次写错误
树枝去重与树层去重都continue就行