文章目录
491 非递增序列
- 表示树层中元素是否重复出现。(-100<= nums[i] <= 100)
for循环
flag = 0; //标记是否重复出现
for(int j = startIndex; j < i; j++){ //从startIndex到当前i的前一个开始遍历
if(nums[j] == nums[i]) {//有重复出现
flag = 1;
break;
}
}
if(flag) continue;//跳过树层中这个数据
set标记
unordered_set uset;
//非递增 || 有重复出现
if((!path.empty() && path.back() > nums[i]) || uset.find(nums[i]) != uset.end()){
continue;
}
uset.insert(nums[i]);//在uset中标记已经出现了一次
哈希优化
int used[201] = {0};
//非递增 || 有重复出现
if((!path.empty() && path.back() > nums[i]) || used[nums[i]+100] == 1) continue;
used[nums[i]+100] = 1;//未出现,标记出现
- 回溯三部曲
- 返回值和参数:nums作为数据的基础提供选择,startIndex表示本树层开始的位置。
- 终止条件:元素都已经遍历完成,到达叶子,表示结束。
if(startIndex == nums.size()) return;
- 单层逻辑:
int used[201] = {0};
for(int i = startIndex; i < nums.size(); i++){
//非递增 || 有重复出现 退出本次循环
if((!path.empty() && path.back() > nums[i]) || used[nums[i]+100] == 1) continue;
used[nums[i]+100] = 1;//未出现,标记出现
path.push_back(nums[i]);//加入path
if(path.size() >= 2) result.push_back(path);
// path长度大于等于2,记录到result中,记录树中的每个节点值
backtracking(nums, i+1);//纵向遍历
path.pop_back();//回溯
}
46 全排列
- 纵向递归去重使用一个数组标记哪个位置之前已经访问过。
- 回溯三部曲:
- 参数与返回值:nums作为基础的数据,used标记哪个位置访问哪个没访问。
- 终止条件:到达树的叶子。
if(path.size() == nums.size()) {
result.push_back(path);
return;
}
- 单层递归
for(int i = 0; i < nums.size(); i++){
if(used[i] == 1) continue;
path.push_back(nums[i]);
used[i] = 1;
backtracking(nums, used);
used[i] = 0;//回溯
path.pop_back();
}
47 全排列Ⅱ
- 去重:
- 树层去重:nums中相同元素使用过就不能再用了。
- 树枝去重(纵向遍历去重):前一层使用过的nums的位置后一层就不能再用了。