C++回溯算法中子集问题分析探讨

 更新时间:2023年03月15日 09:13:02   作者:清风何渡  
回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为回溯点

一、子集

子集问题与其它问题最大的不同就是:每次递归,不止考虑叶子节点,而是考虑所有节点!

体现在代码上,就是每次递归都先result.push_back(path);

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& nums,int index){
        result.push_back(path);
        if(index>=nums.size()) 
            return;
        for(int i=index;i<nums.size();i++){
            path.push_back(nums[i]);
            backtracking(nums,i+1);
            path.pop_back();
        }
    }
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        backtracking(nums,0);
        return result;
    }
};

二、子集II

本题与上题唯一的区别在于:输入样例有重复数字,但又要求结果不能重复

本题与组合总和II是一个套路,即:横向遍历不可重复,纵向遍历可重复

体现在代码上,就是if(i>index&&nums[i]==nums[i-1]) continue;

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& nums,int index){
        result.push_back(path);
        if(index>=nums.size()) return;
        for(int i=index;i<nums.size();i++){
            if(i>index&&nums[i]==nums[i-1])
                continue;
            path.push_back(nums[i]);
            backtracking(nums,i+1);
            path.pop_back();
        }
    }
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        backtracking(nums,0);
        return result;
    }
};

三、递增子序列

这题严格来说并不是子集问题,但是有一点希望和子集II对比一下,就是同一层元素不能重复的问题,这一题因为元素不能排序,所以在判断元素是否重复的问题上,并不能采用类似于上一题的if(i>index&&nums[i]==nums[i-1]) continue;方法,而是应该开辟一个used数组记录每一层元素是否已出现过,其实上一题也能用这种方法,不过上一题没这个必要

还要注意used数组开辟的位置是在backtracking函数内部,意思很明显:used数组只管记录本层元素,至于下一层元素,则要开辟新的ued数组来记录

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& nums,int index){
        if(path.size()>1){
            result.push_back(path);
            if(index==nums.size()) return;
        }
        int used[201]={0};//记录本层元素是否重复使用,新的一层都会重新定义
        for(int i=index;i<nums.size();i++){
            if(used[nums[i]+100]==1||(!path.empty()&&nums[i]<path.back()))
                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) {
        backtracking(nums,0);
        return result;
    }
};

到此这篇关于C++回溯算法中子集问题分析探讨的文章就介绍到这了,更多相关C++回溯算法子集内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c语言动态数组示例

    c语言动态数组示例

    这是一个简单的动态分配数组大小的例子,需要的朋友可以参考下
    2014-04-04
  • QT编写地图实现离线轮廓图的示例代码

    QT编写地图实现离线轮廓图的示例代码

    这篇文章主要介绍了在利用QT编写地图时常常需要用到的离线轮廓图,离线轮廓图使用起来比线轮廓图麻烦一点,需要自己绘制。感兴趣的小伙伴可以学习一下
    2021-12-12
  • C语言实现xml构造解析器

    C语言实现xml构造解析器

    本文给大家分享的是使用C语言来实现xml构造解析器的方法和代码,简单易用,推荐给大家
    2016-07-07
  • C语言中const和C++中的const 区别详解

    C语言中const和C++中的const 区别详解

    这篇文章主要介绍了C语言中const和C++中的const 区别详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • C语言中函数声明与调用问题

    C语言中函数声明与调用问题

    以下是对C语言中的函数声明与调用进行了详细的分析介绍,需要的朋友可以过来参考下
    2013-08-08
  • 基于C语言实现学生管理系统

    基于C语言实现学生管理系统

    这篇文章主要为大家详细介绍了基于C语言实现学生管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 最新C/C++中的new和delete的实现过程小结

    最新C/C++中的new和delete的实现过程小结

    这篇文章主要介绍了C/C++中的new和delete的实现过程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • C语言关键字auto与register及static专项详解

    C语言关键字auto与register及static专项详解

    这篇文章主要解释了c语言中什么是数据类型,什么是变量,他们的真正含义是什么。分析了属性关键字auto,register和static的用法
    2022-07-07
  • 详解C语言中双指针算法的使用

    详解C语言中双指针算法的使用

    双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。本文将通过示例带大家深入了解双指针算法的使用
    2022-08-08
  • C++修炼之构造函数与析构函数

    C++修炼之构造函数与析构函数

    本章节我们将学习类的6个默认成员函数中的构造函数与析构函数,并对比C语言阶段的内容来学习它们的各自的特性,感兴趣的同学可以参考阅读
    2023-03-03

最新评论