【进击的算法】基础算法——回溯算法

news2024/11/24 9:08:54

🍿本节主题:回溯算法
🎈更多算法:深入聊聊KMP算法
💕我的主页:蓝色学者的个人主页

文章目录

    • 一、前言
    • 二、概念
    • 三、例题
      • 1.题目:全排列
      • 2.解题思路
        • 回溯算法的本质
          • 问题1:
          • 问题2:
          • 问题3:
      • 3.总结
      • 4.参考代码
    • 四、作业
    • 五、结语

一、前言

很开心又跟大家见面了,今天我们来一起学习一下回溯算法的基本思想,完成一道经典题目的讲解(全排列),之后我还会留下本节课的小作业,感兴趣的话一起来看看把~

二、概念

回溯算法,又称试探法,外文名(backtrackingalgorithm)这也是为什么我们经常在定义回溯函数的时候为函数取名为 backtracking ,回溯算法正如其名,在有多种选择的情况下,回溯算法会试探性的挨个选择,接着再回退到选择前的状态。

其实,回溯算法本质上也是一个暴力算法

为什么说回溯算法本质上也是暴力算法呢,我们通过接下来的一个例题来为大家解释一下

三、例题

1.题目:全排列

全排列:leetcode链接:https://leetcode.cn/problems/permutations/
本题给定我们一个不含重复数字的数组 nums ,返回其 所有可能的全排列可以按任意顺序返回答案。

示例1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]

2.解题思路

全排列想必大家在初高中都应该接触过,那么我们都会使用一种方法:定住一项,让后面交换位置,从而达到目的,比如:

定住1那么还有2和3,一种结果是{1,2,3} ,交换位置得{1,3,2}
定住2那么还有1和3,一种结果是{2,1,3} ,交换位置得{2,3,1}
定住3那么还有1和2,一种结果是{3,1,2} ,交换位置得{3,2,1}

这样我们便得到了{1,2,3}的全排列

但是假如我们要求:{1,2,3,4}的全排列呢?

很显然我们交换元素的逻辑就会变得复杂,2和3交换完以后,4怎么办?很显然这样会让我们大脑短路,如何才能求出呢?

                 回溯算法引入

回溯算法的本质

其实回溯算法本质上也是一种暴力的算法,他解决了我们在交换问题上的困惑,还拿刚刚{1,2,3}的例子:
图片1.1
如图,我将上述过程整理成了一张图片,方便大家学习感悟,在这里,我想问大家两个问题:

1.第一次取1,第二次怎么取2?第三次怎么取3?
2.什么时候该回溯?
3.回退到哪里?

相信这两个问题搞清楚了,你的回溯算法就算是听懂了,下面我来一一回答一下这三个问题:

问题1:

我们可以定义一个循环让此循环能够遍历完{1,2,3}

for(int i = 0;i<n;i++)

for(int i = first;i<n;i++)

1.我们只需要每次让下标为i位置的元素与第一个元素交换即可,这样我们不就能拿到分别以1,2,3开头的元素了吗,当我们确定了第一个元素,剩下的元素应当也按照这样的逻辑进行交换,注意此时就不再是与0号下标交换,而是与第一个不确定位置的下标交换,也就是first

2.在固定好一个数字后,我们需要依次确定其他数字,所以要重复上述过程,直到所有数字都被固定了,因此我们采用递归的思路来完成。

问题2:

当什么时候应该回溯呢?按照上文的逻辑,我们不难得出当得到与原数组相同长度的数组时,我们就可以保存结果,向上回退了

问题3:

回退到哪里?比如我们确定1后,选择了2,我们自然能确定{1,2,3},但我们还漏下了选择3之后,确定{1,3,2}的情况,自然要回退到没选择2的时候,想想我们第一个问题,不难得出,我们交换后,还要再交换回来,这是回溯算法的精髓

3.总结

这道题目是一道很经典的回溯算法题目,先把上面我回答的三个问题看清楚,再去挑战这道题会轻松很多,如果你对哪一步仍有疑问,可以试着多看一下我上面画的图,多回想上面的三个问题,一定会有所收获。

4.参考代码

class Solution {
public:
    void backtrack(vector<vector<int>>& res, vector<int>& output, int first, int len)   
    {
        // 到达数组最大长度
        if (first == len) 
        {
            res.emplace_back(output);
            return;
        }
        for (int i = first; i < len; ++i) 
        {
            // 交换
            swap(output[i], output[first]);
            // 递归确定下一个数
            backtrack(res, output, first + 1, len);
            // 交换回来
            swap(output[i], output[first]);
        }
    }
    vector<vector<int>> permute(vector<int>& nums) 
    {
        vector<vector<int> > res;
        backtrack(res, nums, 0, nums.size());
        return res;
    }
};

四、作业

✨消化吸收完本次讲解的内容后,大家可以试着去挑战两道题目
🎉如果你还未熟练掌握回溯算法:组合问题https://leetcode.cn/problems/combinations/
🎉如果你已熟练掌握了回溯算法:N皇后
https://leetcode.cn/problems/n-queens/
🎶之后的回溯练习文章里我还会详细讲解这两道题,期待的话可以点一下收藏

五、结语

到这里,我们就学完了回溯算法里最经典的题目,我们知道回溯算法其实也是一种暴力算法,其实对于有些问题,能够暴力写出就已经很不错了,比如N皇后问题,因此回溯算法也是很有必要掌握的

如果你感觉有所收获的话,可以 点赞+评论+收藏支持学者哦下次见

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

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

相关文章

linux 解压命令------超详细

目录 一、前期准备&#xff1a; 二、安装finalShell并与虚拟机进行连接 三、上传数据到虚拟机 四、解压命令练习 1. 解压zip包 unzip apache-maven-3.6.3-bin.zip 2. 解压tar.gz包 tar -zxvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz 一、前期准备&#xff1a; 1.final…

Redis命令及其数据类型详解

前面的文章我们讲解过关于Redis的安装: 手把手教你Linux下安装部署Redis&#xff0c;今天我们具体的讲一下Redis的命令及其5种数据类型 Redis命令 Redis命令用于在redis服务上来执行某些特定操作。 这里我们以Linux下的操作为例&#xff1a; 进入到我们Redis的bin目录下&am…

企业档案信息化规划总体框架

按照《中华人民共和国档案法》《企业档案管理规定》《企业档案工作规范》《企业数字档案馆&#xff08;室&#xff09;建设指南》等政策文件要求&#xff0c;企业档案信息化建设应从基础设施体系、应用系统体系、档案资源体系、标准规范体系、安全保障体系、组织人才体系六方面…

ARM公司发展史

1. 前言 当前&#xff0c;X86和ARM架构是公认的在商业化进程中表现最优秀的两大架构。之前我们已经介绍了X86架构&#xff0c;今天介绍另一个在近十年大火的架构&#xff0c;ARM。 ARM架构&#xff0c;过去称作进阶精简指令集机器&#xff08;Advanced RISC Machine&#x…

【Java】【系列篇】【Spring源码解析】【二】【整体】【Spring整体流程解析】

本篇文章的目的是希望对Spring运行有个整体上的了解&#xff0c;后面的文章都是基于此12大步骤 读完这篇文章&#xff0c;你可以了解到&#xff1a; 1.spring运行的大致流程&#xff0c;他在这个期间做了哪些事 2.xml方式和注解方式载入BeanDifinition的时机一、Spring的运行的…

AgentTesla 掀起攻击全球各地企业的浪潮

大量带有恶意附件的电子邮件发送到南美洲与欧洲的企业。从 2022 年 8 月 12 日开始针对西班牙、葡萄牙、罗马尼亚和南美洲多个国家的企业进行发送&#xff0c;后续针对德国与阿根廷的企业发起了更大规模的攻击&#xff0c;迄今为止已经发送了超过 26000 封邮件。 感染链 攻击…

[MRCTF2020]Ez_bypass

目录 信息收集 代码审计 第一个判断 第二层判断 传参方式 补充说明 信息收集 打开靶场页面显示给出提示 I put something in F12 for you include flag.php; $flagMRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}; if(isset($_GET[gg])&&isset($_GET[id])) { $id$_GET[i…

大数据技术架构(组件)6——Hive:流程剖析3

1.1.3、Statistics Job从OperatorTree生成Job的过程:1、对输出表生成MoveTask2、从OperatorTree中的一个根节点向下深度优先遍历3、ReduceSinkOperator标识Map/Reduce界限&#xff0c;多个Job间的界限4、遍历其他根节点&#xff0c;遇到JoinOpeartor合并MapReduceTask5、生成St…

JavaWeb-RequestResponse

JavaWeb-Request&Response 1&#xff0c;Request和Response的概述 Request是请求对象&#xff0c;Response是响应对象。这两个对象在我们使用Servlet的时候有看到&#xff1a; 此时&#xff0c;我们就需要思考一个问题request和response这两个参数的作用是什么? requ…

放假第一二天

假期 # 生活 # 水文 每年放假回家都会发生很多有意义或者说有意思、开心、喜庆的事情&#xff0c;而在我孩童时期那只能是一段段回忆&#xff1b;至于现在则是我朋友圈众多记录中的一条。 但是&#xff0c;从现在开始我想尝试尝试在发朋友圈的基础上再加一个文字叙述&#xff…

C语言:函数

往期文章 C语言&#xff1a;初识C语言C语言&#xff1a;分支语句和循环语句 目录往期文章前言1. 函数是什么2. 库函数3. 自定义函数4. 函数的参数5. 函数的调用6. 函数的嵌套调用和链式访问6.1 函数嵌套调用6.2 函数的链式访问7. 函数的声明和定义8. 函数的递归后记前言 今天…

什么是无线网桥?全方位解析无线网桥及应用场景

欢迎来到东用知识小课堂&#xff01;1.无线网桥介绍无线网桥的主要用途就是用于桥接两个网络&#xff0c;它可以取代网线&#xff0c;在不方便布线的环境或是无法挖沟埋管&#xff0c;环境已经既定无法再去破坏的环境当中通过无线微波的传输方式&#xff0c;进行网络、视频、数…

Android ViewModel,Lifecycles和LiveData组件讲解

文章目录一、ViewModelViewModel基本用法向ViewModel传递参数二、Lifecycles三、LiveDataLiveData的基本用法map和switchMapJetPack是一个开发组件工具集&#xff0c;他的主要目的是帮助我们编写出更加简洁的代码&#xff0c;并简化我们的开发过程。JetPack中的组件有一个特点&…

【C++11】右值引用

右值引用是C11中才被提出来的新概念&#xff0c;而以前的版本中也有引用&#xff0c;但是是指的左值引用。归根结底&#xff0c;左右值引用都是给对象取别名。 1.区分左值和右值 提起左值和右值很多小伙伴可能第一时间会有点小蒙圈&#xff0c;敲了好长时间代码了&#xff0c;对…

【Java基础】—— Java简介(超详细整理,适合新手入门)

​ “作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴。 写给小白看的入门级 Java 基本语法&#xff0c;需要掌握哪些知识点? Java涵盖的知识点…

1个 30多年程序员的生涯经验总结

有人说&#xff1a;一个人从1岁活到80岁很平凡&#xff0c;但如果从80岁倒着活&#xff0c;那么一半以上的人都可能不凡。 生活没有捷径&#xff0c;我们踩过的坑都成为了生活的经验&#xff0c;这些经验越早知道&#xff0c;你要走的弯路就会越少。 在我30多年的程序员生涯里…

部分iphone、安卓手机打开微信小程序不请求、白页问题

前言&#xff1a; 最近项目上发现用户测试小程序体验版打开一直白页&#xff0c;请求没反应&#xff0c;页面不渲染。开始以为是微信小程序某api问题&#xff0c;或者用户微信版本过低&#xff0c;或者用户网络不好&#xff0c;甚至考虑是不是服务器问题&#xff01;因为后端是…

vue3中如何使用JSX?

在绝大多数情况下&#xff0c;Vue 推荐使用模板<template>语法来创建应用。 在 Vue 3 的项目开发中&#xff0c;template 是 Vue 3 默认的写法。虽然 template 长得很像 HTML&#xff0c;但 Vue 其实会把 template 解析为 render 函数&#xff0c;之后&#xff0c;组件运…

【Java多线程】线程的优先级

线程的优先级等级 MAX_PRIORITY&#xff1a;10 MIN _PRIORITY&#xff1a;1 NORM_PRIORITY&#xff1a;5 涉及的方法 getPriority() &#xff1a;返回线程优先值 setPriority(int newPriority) &#xff1a;改变线程的优先级 例&#xff1a; 我们将分线程的优先级设置为…

Java设计模式-迭代器模式Iterator

介绍 根据GoF的定义&#xff0c;迭代器模式提供了一种顺序访问聚合对象的元素而不暴露其底层表示的方法。这是一种行为设计模式。 顾名思义&#xff0c;迭代器有助于以定义的方式遍历对象集合&#xff0c;这对客户端应用程序很有用。在迭代期间&#xff0c;客户端程序可以根据需…