代码随想录

本文介绍了在处理递增子序列和全排列问题时,如何利用递归、set数据结构以及used数组进行去重,确保子序列的唯一性和正确性。重点在于理解如何在代码中设置终止条件和处理重复元素以生成满足要求的子序列或排列。
摘要由CSDN通过智能技术生成

491.递增子序列

思路:代码随想录

思路:本题跟子集2不一样,无法排序,也就是在去重上我们无法使用bool数组来去重,所以本题我们要使用set来去重。三部曲: 

  • 递归函数参数

本题求子序列,很明显一个元素不能重复使用,所以需要startIndex,调整下一层递归的起始位置。

代码如下:

vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums, int startIndex)

终止条件:

题目要求递增子序列大小至少为2 所以 path.size()>1。终止条件跟子集问题一样,我们需要遍历整棵树,所需不需要写。

单层递归逻辑。

for循环外定义一个set。循环取数,如果当前path不为空且你取得这个值比path最右边的值小或当前取得数在set中有。就continue。

取过的数加入set。

 unordered_set<int> 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();

        }

46 全排列

思路:代码随想录 

思路:排列问题跟组合问题不一样的点是:i 从0开始遍历而不是startindex,因为排列可以取前面的元素比如说【1,2】,【2,1】是2个排列。此外我们还需要used数组来避免一个元素取两次。终止条件:我们在叶子节点收集结果,所以当path.size() == nums.size()时 就收集结果

for (int i = 0; i < nums.size(); i++) {
    if (used[i] == true) continue; // path里已经收录的元素,直接跳过
    used[i] = true;
    path.push_back(nums[i]);
    backtracking(nums, used);
    path.pop_back();
    used[i] = false;
}

全排列2

思路: 代码随想录

 

思路:本题在上一题基础上有重复元素,要去重使用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++) {
            // used[i - 1] == true,说明同一树枝nums[i - 1]使用过
            // used[i - 1] == false,说明同一树层nums[i - 1]使用过
            // 如果同一树层nums[i - 1]使用过则直接跳过
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
                continue;
            }
            if (used[i] == false) {
                used[i] = true;
                path.push_back(nums[i]);
                backtracking(nums, used);
                path.pop_back();
                used[i] = false;
            }
        }
    }

 为什么要if(used[i]==false)才执行取数操作呢,为了防止重复取数。因为used数组会标记取过的数。而for循环是从0开始的,所以需要这一步。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值