回溯算法(1)组合

news2024/11/17 9:43:40

文章目录

  • 回溯算法理论
  • 77. 组合
  • 216. 组合总和
  • 17. 电话号码的组合

回溯算法理论

回溯算法其实就是递归,只不过递归又分为递去归来,其中归来便就是回溯

为什么要使用回溯?
有些问题我们通过暴力解法也很难解决,比如说我们接下来要讲的这几道题,他们的共性是我们都需要大量的for循环来遍历某个序列,但是其中for循环的次数随着条件的改变而改变,通过暴力,我们很难找到某一个问题的通解。

注意:回溯本身就是递归,而递归就是不断穷举所有可能性的过程,所以,一般情况下,我们应该能使用迭代就使用迭代,迫不得已再使用递归(回溯)来解决问题。


回溯算法的理解:
因为回溯一般解决的都是在一个大的集合中寻找子集的情况,所以我们可以把这个大的集合看作一个二叉树,回溯就是遍历二叉树,找到所有叶子节点的过程。
集合的大小: 构成二叉树的宽度(集合越大,二叉树就越宽)
寻找或操作的次数:构成二叉树的深度,也是回溯的深度。

假设我们的集合大小为4,根据集合的初始位置得到子集和的初始位置,进而操作得到子集和。


回溯模板:

void dfs()
{
	if (符合某种条件)
	{
		进行记录操作(在一般的回溯过程中,我们需要记录符合条件的子集合)
		return;
	}
	for (遍历本层的各个节点)
	{
		对于一个未被操作的节点:记录下此节点,把他当作一个新的根节点,遍历其子树
		dfs();//进入递归
		到达了叶子节点并且操作完成,弹出此节点,继续遍历下一节点
	}
}

大的圆圈表示我们的第一层for循环的遍历过程,小的圆圈表示我们每次递归后的子for循环。
在这里插入图片描述


总结:回溯法解决的问题都可以抽象为树形结构

77. 组合

力扣传送门:
https://leetcode.cn/problems/combinations/?envType=study-plan&id=suan-fa-ru-men&plan=algorithms&plan_progress=1syarli

题目:

列出所有 [1,n]的长度为k的子集和。

这道题算是我们回溯算法的入门题目,当我们使用for循环时,我们需要大量的嵌套for循环,甚至无法暴力解决,因此我们只能使用回溯的算法解决。

本题回溯算法:就是在一个for循环中进入递归,然后隐式的调用 n 个for循环,其实就是穷举出所有可能性。


在这里插入图片描述

class Solution {
private:
    vector<vector<int>> res;//存储最后的结果(所有的叶子节点)
    vector<int> temp;   //存储一个叶子节点(子集和)
public:
    void dfs(int n,int k,int startIdx)
    {
    	//当表示叶子节点的数组大小为k时,说明找到了某个子集和,存储进结果中
        if (temp.size()==k)
        {
            res.emplace_back(temp);
            //到达了叶子节点,递归终止
            return;
        }
        //依次遍历每一层的同级节点(看图)
        for (int i=startIdx;i<=n;i++)
        {
        	//存储每一个子树的根节点
            temp.push_back(i);
            //子树进入递归,再次重复上面的操作
            dfs(n,k,i+1);
            //返回上一层,弹出最后的节点
            temp.pop_back();
            //然后接着遍历同级的下一节点
        }
    }
    vector<vector<int>> combine(int n, int k) {
        dfs(n,k,1);
        return res;
    }
};

剪枝操作:
看图:
在这里插入图片描述
当我们要取4个数字时,先看第二层:由于我们在取得1之后可以在取3个,因此节点1满足这个情况,但是节点2,3,4都不能再取得三个数字,所以可以直接退出此循环;节点1中取三个数字后的情况也是如此。

因此,剪枝(递归优化)的代码:

class Solution {
private:
    vector<vector<int>> res;    //存放总的结果
    vector<int> temp;           //存放一次的结果
public:
    void dfs(int n,int k,int startIdx)
    {
        if (temp.size()==k)
        {
            res.emplace_back(temp);  //将这一次的结果存放进整个结果中
            return;
        }
        for (int i=startIdx;i<=n-(k-temp.size())+1;i++)
        {
            temp.push_back(i);
            dfs(n,k,i+1);
            temp.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        dfs(n,k,1);
        return res;
    }
};

216. 组合总和

力扣传送们:
https://leetcode.cn/problems/combination-sum-iii/description/

本题与上一题基本一致,就是把用回溯模拟的树的深度增大到了9,因为是从[1,9]中随机抽取,所以我们的树应该深度为9,

class Solution {
private:
    vector<vector<int>> res;
    vector<int> temp;
public:
    void dfs(int k,int n,int startIdx)
    {
    	//计算总和
        int sum=accumulate(temp.begin(),temp.end(),0);
        //判断总和是否相等,并且元素个数是否为k个
        if (sum==n && k==temp.size())
        {
            res.emplace_back(temp);
            return;
        }
        //for循环:横向遍历
        //递归:纵向递归
        for (int i=startIdx;i<=9;i++)
        {
            temp.push_back(i);
            dfs(k,n,i+1);
            temp.pop_back();
        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        dfs(k,n,1);
        return res;
    }
};

17. 电话号码的组合

力扣传送门:
https://leetcode.cn/problems/letter-combinations-of-a-phone-number/solutions/

class Solution {
private:
    vector<string> res;
    string temp;
    unordered_map<char, string> phoneMap{
            {'2', "abc"},
            {'3', "def"},
            {'4', "ghi"},
            {'5', "jkl"},
            {'6', "mno"},
            {'7', "pqrs"},
            {'8', "tuv"},
            {'9', "wxyz"}
        };
public:
    void dfs(int index,string& s)
    {
        if (s.size()==index)
        {
            //长度相同
            res.emplace_back(temp);
            return;
        }
        //取出子字符串
        char digit=s[index];
        string lit_str=phoneMap[digit];
        for (int i=0;i<lit_str.size();i++)
        {
            temp.push_back(lit_str[i]);
            dfs(index+1,s);
            temp.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        if (digits.size() == 0) {
            return res;
        }
        dfs(0,digits);
        return res;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/73038.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言学习之路(高级篇)—— 变量和内存分布(上)

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 数据类型 1) 数据类型概念 什么是数据类型&#xff1f;为什么需要数据类型? 数据类型是为了更好进行内存的管理&#xff0c;让编译器能确定分配…

04 | 云硬盘的使用方法

前期环境&#xff1a; Ubuntu 0 云硬盘类型 云硬盘类型包括&#xff1a; 高性能云硬盘通用型 SSD 云硬盘SSD 云硬盘增强型 SSD 云硬盘极速型 SSD 云硬盘&#xff0c;仅支持随存储增强型云服务器一同购买&#xff0c;不支持单独购买 1 创建云硬盘 1.1 创建方式 1.1.1 单个…

第二证券|连拉20CM涨停!防疫新概念股火了!恒生科技指数涨逾5%

周四上午&#xff0c;“新十条”发布后&#xff0c;由于A股商场已反弹一段时刻&#xff0c;两市股指今天早盘接连震动走势&#xff0c;港股在地产、科技、消费等板块带动下&#xff0c;体现更为强势。 A股上证指数早盘在3200点附近持续震动&#xff0c;光伏、化肥、物流、港口等…

JavaScript内置对象(内置对象、查文档(MDN)、Math对象、日期对象、数组对象、字符串对象)

目录 JavaScript内置对象 内置对象 查文档 MDN Math对象 Math概述 案例一&#xff1a;封装自己的对象 随机数方法 random() 案例一&#xff1a;猜数字游戏 日期对象 Date 概述 Date()方法的使用 获取日期的总的毫秒形式 案例一&#xff1a;倒计时效果 数组对象 …

DoltLab本地部署实践

目录引言Dolt是什么&#xff1f;如何本地部署使用DoltLab具体安装步骤安装期间FAQ写在最后其他相关资料引言 自从搞深度学习训练模型以来&#xff0c;一直有个问题困扰着我&#xff1a;训练所用数据集的管理。为什么说这是一个问题呢&#xff1f; 在读研时&#xff0c;我们依据…

ELK日志分析系统概述及部署

文章目录一、ELK日志分析系统1、概念2、完整日志系统基本特征3、使用ELK的原因4、ELK 的工作原理二、ELK日志分析系统集群部署的操作步骤环境准备&#xff1a;1、 ELK Elasticsearch 集群部署&#xff08;在Node1、Node2节点上操作&#xff09;1.1、更改主机名、配置域名解析、…

剑指 Offer 53 - I. 在排序数组中查找数字 I

摘要 剑指 Offer 53 - I. 在排序数组中查找数字 I 一、二分查找 1.1 二分查找的分析 由于数组已经排序&#xff0c;因此整个数组是单调递增的&#xff0c;我们可以利用二分法来加速查找的过程。 考虑 target在数组中出现的次数&#xff0c;其实我们要找的就是数组中「第一…

汇编语言ch2_2 汇编语言中的debug

使用debug 可以完成以下功能&#xff1a; 可以查看 和改变 CPU 中&#xff0c;寄存器的内容&#xff1b;可以查看 和改变内存中的内容&#xff1b;可以将内存中的 机器指令 翻译成汇编指令使用汇编指令 在 内存中 存入 机器指令执行机器指令 首先&#xff0c;启动 Debug,在DO…

实现数智内控,数据分析创造价值——辽宁烟草智能风险体检系统

近两年&#xff0c;烟草行业部分单位围绕中心任务&#xff0c;结合实际&#xff0c;守正创新&#xff0c;开展了许多研究探索。比如&#xff0c;在财务大数据价值挖掘、会计共享中心建设、财务风险预警系统建设等方面做了大量卓有成效的工作。在这样的背景下&#xff0c;辽宁烟…

DSPE-MAL 磷脂改性马来酰亚胺简介CAS1360858-99-6

DSPE-MAL二硬脂酰磷脂酰乙醇胺改性马来酰亚胺 中文名称&#xff1a;二硬脂酰磷脂酰乙醇胺改性马来酰亚胺 英文名称&#xff1a;DSPE-MAL CAS&#xff1a;1235864-97-7 分子式&#xff1a;C48H86N2NaO11P 分子量&#xff1a;921.16700 外观&#xff1a;白色粉末 DSPE-MAL二…

2022icpc 济南站 持续补题

链接&#xff1a;Dashboard - 2022 International Collegiate Programming Contest, Jinan Site - Codeforces 签到题&#xff1a;k K. Stack Sort You are given a permutation with nn numbers, a1,a2,…,an(1≤ai≤n,ai≠aj when i≠j). You want to sort these numbers …

WY易盾cb、fp逆向分析

内容仅供参考学习 欢迎朋友们V一起交流&#xff1a; zcxl7_7 目标 网址&#xff1a;案例地址 这个好像还没改版&#xff0c;我看官网体验那边已经进行了混淆 分析 这个进行的请求很乱&#xff0c;我就不说怎么找的了&#xff0c;到时候越听越乱。一共有2个请求很重要 …

笔试题之编写SQL按要求查询用户阅读行为数据

紧张源于恐惧&#xff0c;恐惧源于未知。 文章目录前言一、SQL题目二、当时作答结果三、复盘&#xff08;一&#xff09;建表并自定义插入数据&#xff08;二&#xff09;正确解答&#xff08;三&#xff09;答错原因分析总结前言 分享本人一次失败的笔试经历&#xff0c;供各…

plink中的BGEN格式的数据如何用

这里&#xff0c;介绍一下BGEN格式的数据&#xff0c;他的文件格式是这样的&#xff1a;a.bgen&#xff0c;这是一个新的数据格式&#xff0c;目前应用不如plink的二进制文件&#xff1a;.bim,.bed,.fam。这里介绍一下如何相互转换。 1. bgen格式介绍 现代遗传关联研究通常使…

[附源码]计算机毕业设计JAVA中小企业人事管理系统

[附源码]计算机毕业设计JAVA中小企业人事管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM my…

HMS Core 6.8.0版本发布公告

分析服务 ◆ 游戏行业新增“区服分析”埋点模板及分析报告&#xff0c;支持开发者分服务器查看用户付费、留存等指标&#xff0c;可进一步评估不同服务器的玩家质量&#xff1b; ◆ 新增营销活动报告&#xff0c;可查看广告任务带来的曝光、点击相关信息&#xff0c;让营销推…

阿里P7晒工资条,看完真的扎心了……

前几天&#xff0c;有位老粉私信我&#xff0c;说看到某95后学弟晒出阿里P7的工资单&#xff0c;他是真酸了…想狠补下技术&#xff0c;努力冲一把大厂。 为了帮到他&#xff0c;也为了大家能在最短的时间内做面试复习&#xff0c;我把软件测试面试系列都汇总在这一篇文章了。…

关于信息系统监理师考试怎么备考?

信息系统监理师是属于软考的中级科目&#xff0c;是水平考试&#xff0c;取得证书后就具备了任职中级职称的资格&#xff0c;并可以注册为信息系统监理师&#xff0c;进行信息系统监理工程师的执业工作。 注册监理工程师&#xff0c;是指经考试取得中华人民共和国监理工程师资…

041-推箱子游戏1

上一讲:040-JAVA集合及GUI综合应用(实现简单的订单管理系统)_CSDN专家-赖老师(软件之家)的博客-CSDN博客 下一讲:推箱子游戏源代码 摘要: 1、使用JAVA基础知识 2、GUI界面编程实现推箱子界面,常用控件的综合应用; 3、使用JAVA绘图技术实现推箱子过程的绘图功能;…

追觅身陷「多事之秋」!一场无法投机的「卡位战」

清洁电器市场正释放着新的商业活力。 GfK数据显示&#xff0c;今年上半年在整体家电市场低迷的同时&#xff0c;清洁机器人市场零售额保持了同比15%的增速&#xff0c;仍然是家电行业的主要增长点。其中&#xff0c;线上市场扫地机器人销售仍然居首位&#xff0c;但洗地机反超…