代码随想录Day20 回溯算法 LeetCode77 组合问题

以下内容更详细解释来自于:代码随想录 (programmercarl.com)

1.回溯算法理论基础

回溯法也叫回溯搜索法,是搜索法的一种,我们之前在二叉树中也经常使用到回溯来解决问题,其实有递归就有回溯,有的时候回溯隐藏在递归之下,我们不容易发觉,今天我们来详细介绍一下什么是回溯,它能解决哪些问题.

回溯法效率

回溯法的效率是不高的,回溯的本质是穷举,因为有些问题能用回溯法解决出来就不错了,别无他法,只能使用这个暴力方法

回溯法,一般可以解决如下几种问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 棋盘问题:N皇后,解数独等等
  • 提供一个八皇后小游戏hhh:【死亡8皇后】小游戏_游戏规则玩法,高分攻略-2345小游戏

理解回溯法的方式

不要光靠脑子想,要将这种回溯具象化,想象成树形结构,任何回溯法解决的问题都可以转化为树形结构来解决问题.

因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度,都构成的树的深度.

递归就要有终止条件,所以必然是一棵高度有限的树(N叉树).

回溯法代码模板(伪代码)

首先是函数参数和返回值

一般无需返回值,参数很多,一般边写边定,函数名一般定为backtracking

void backtracking(参数)

终止条件

我们说可以将回溯算法想像成一个树形结构,那么我们就一定有终止条件,一般到达终止条件(叶子结点),也就是我们收获答案的时候,相关为伪代码如下

if (终止条件) {存放结果;return;
}

回溯搜索的遍历过程

上文中我们说回溯的树的宽度取决于元素个数,回溯深度取决于递归深度,如图所示

回溯算法遍历的伪代码如下

for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {处理节点;backtracking(路径,选择列表); // 递归回溯,撤销处理结果
}

注意这里的撤销,假设我们要求1234中size为2的组合,有 12 13....这里假设我们第一个节点是12,这里我们要得到13就得将2pop出去,也就是我们回溯撤销的过程.

回溯模板(全)

void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {处理节点;backtracking(路径,选择列表); // 递归回溯,撤销处理结果}
}

 

2.经典例题 :LeetCode T77 组合问题

题目链接:77. 组合 - 力扣(LeetCode)

题目思路:

我们说递归有三部曲,这里我们回溯也有三部曲,这里我们首先定义一个path变量,来存放我们每条路径上的结果,因为这里我们可以将回溯过程想象成n叉树,所以叶子结点的结果也可以想象成路径的结果,然后定义一个result数组来存放所有路径的集合,这里我们定义为全局变量,下面函数实现中直接操作即可.

List<Integer> path = new ArrayList<>();
List<List<Integer>>  result = new ArrayList<>();

我们以1234中排列2个数字,即n = 4,k = 2为例,画出如下图

回溯三部曲

1.确定函数参数和返回值

这里n和k肯定是需要的,还有我们需要一个参数就是从哪里开始,于是我们定义一个变量startIndex来记录每次递归开始的逻辑,比如第一次从1开始,第二次从2开始

public void backtracking(int n, int k,int startIndex)

2.确定终止条件

这里的终止条也是收割结果的时候,我们发现树的叶子节点就是我们所要的结果,我们写出如下代码 

        //终止条件if(path.size() == k){result.add(new ArrayList<>(path));return;}

3.确定一次递归(回溯)过程

这里我们按照上文所说就是我们for循环该登场了,这个时候我们的循环就得从startIndex开始到n结束,里面需要做的事情就是path.add元素,再进行backtracking,最后得pop元素进行一次回溯的过程,这里我们可以想象假设上面这个1234的例子,这里我收集了12这个例子,我想收获13这个结果是不是得将2弹出再将3进行添加呀,下面是代码演示

        //for循环for(int i = startIndex;i<=n;i++){path.add(i);backtracking(n,k,i+1);path.remove(path.size()-1);}

题目代码:

class Solution {List<Integer> path = new ArrayList<>();List<List<Integer>>  result = new ArrayList<>();public List<List<Integer>> combine(int n, int k) {backtracking(n,k,1);return result;}public void backtracking(int n, int k,int startIndex){//终止条件if(path.size() == k){result.add(new ArrayList<>(path));return;}//for循环for(int i = startIndex;i<=n;i++){path.add(i);backtracking(n,k,i+1);path.remove(path.size()-1);}}
}

代码优化

还是以上面1234举例,这里我们可以进行一次剪枝,假设我们n = 4,k = 4我们就会发现startIndex取2后面的值就毫无意义了,这里我们就可以对这种情况剪枝,如果后面的元素不足以我构成我们的一次正确的结果,就不要去遍历它了

优化过程如下:

  1. 已经选择的元素个数:path.size();

  2. 还需要的元素个数为: k - path.size();

  3. 在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历

为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。

举个例子,n = 4,k = 3, 目前已经选取的元素为0(path.size为0),n - (k - 0) + 1 即 4 - ( 3 - 0) + 1 = 2,这里都是合理的

只需修改一下for循环的区间即可

for (int i = startIndex; i <= n - (k - path.size()) + 1; i++)

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv5网络结构图

网络结构图&#xff08;简易版和详细版&#xff09; 网络框架介绍 前言&#xff1a; YOLOv5是一种基于轻量级卷积神经网络&#xff08;CNN&#xff09;的目标检测算法&#xff0c;整体可以分为三个部分&#xff0c; backbone&#xff0c;neck&#xff0c;head。 如上图所示…

netca_crypto.dll找不到怎么修复?详细解决办法和注意事项

当你在使用计算机时&#xff0c;突然出现了一个错误提示&#xff1a;“netca_crypto.dll 找不到”。不知道该如何解决这个问题&#xff1f;其实要解决是非常的简单的&#xff0c;今天我们将为你提供几种修复 netca_crypto.dll 找不到的解决方法和一些注意事项。在深入探讨修复方…

ARM day9

src/key_it.c #include "key_it.h" #include "led.h" void key_it_config() {//RCC使能GPIOF时钟RCC->MP_AHB4ENSETR | (0x1<<5);//设置PF9 PF7 PF8GPIO输入//PF9GPIOF->MODER & (~(0x3<<18));//PF8GPIOF->MODER & (~(0x3&l…

进来“抄作业”!示例代码、操作手册,尽在华为云Codelabs!

1 Codelabs 简介 1.1 什么是 Codelabs&#xff1f; Codelabs 是华为云开发者工具&#xff0c;提供互动式的&#xff0c;以实践为主的教程&#xff0c;这些教程旨在指导开发者通过实际操作来学习新的编程技能、工具、框架。华为云 Codelabs 提供丰富的华为云产品代码示例/操…

Redis 集群 Redis 事务 Redis 流水线 Redis 发布订阅 Redis Lua脚本操作

Redis 集群 & Redis 事务 & Redis 流水线 & Redis 发布订阅 Redis 集群linux安装redis主从配置查看当前实例主从信息 Redis Sentinelsentinel Redis Cluster Redis 事务Redis 流水线Redis 发布订阅Redis Lua脚本操作 Redis 集群 linux安装redis 下载安装包&#…

数据结构之手撕链表(讲解➕源代码)

0.引言 我们在学习过顺序表之后&#xff0c;会发现两点不是很优秀的操作&#xff1a; 1.顺序表的头插和中间的插入&#xff1a; 非常麻烦&#xff0c;需要不断的覆盖数据。 2.动态开辟空间&#xff1a; a.一般动态开辟的空间都是以2倍的形式开辟&#xff0c;当…

xml的语法

<!-- 1、每一个xml,有且只有一个根标签&#xff0c;所有xml标签必须写在根标签中 2、标签必须要有合闭 3、xml格式是否正确&#xff0c;可以通过浏览器打开xml。来校验xml格式是否正确 4、xml是区别大小写的 5、xml书写标签名时&#xff0c;不要出现空格等特…

centos 7.9离线安装wget

1.下载安装包 登录到wget官网上下载最新的wget的rpm安装包到本地 http://mirrors.163.com/centos/7/os/x86_64/Packages/ 2.上传安装包到服务器 3.安装 rpm -ivh wget-1.14-18.el7_6.1.x86_64.rpm 4.查看版本 wget -V

集合的进阶

不可变集合 创建不可变的集合 在创建了之后集合的长度内容都不可以变化 静态集合的创建在list &#xff0c;set &#xff0c;map接口当中都可以获取不可变集合 方法名称说明static list of(E …elements)创建一个具有指定元素集合list集合对象staticlist of(E…elements)创…

智慧港口与无人机巡逻技术:走进未来的海上交通枢纽

在21世纪&#xff0c;随着全球贸易的日益繁荣&#xff0c;港口作为连接世界各地的重要交通枢纽显得尤为重要。为了提高港口的效率和安全性&#xff0c;智慧港口和无人机巡逻技术成为了最前沿的选择。其中&#xff0c;复亚智能无人机技术在智慧港口的建设和日常运营中扮演了至关…

6、docker下mysql修改配置文件

1、查看mysql镜像 如果没有mysql镜像则下载 docker images |grep mysql 2、查看mysql容器 docker ps |grep mysql 如果没有显示mysql容器信息&#xff0c;则创建 3、创建容器 docker run -it --name mysql-test -e MYSQL_ROOT_PASSWORDroot -p 3306:3306 -d f9653 4、在…

消息队列缓存,以蓝牙消息服务为例

前言 消息队列缓存&#xff0c;支持阻塞、非阻塞模式&#xff1b;支持协议、非协议模式 可自定义消息结构体数据内容 使用者只需设置一些宏定义、调用相应接口即可 这里我用蓝牙消息服务举例 有纰漏请指出&#xff0c;转载请说明。 学习交流请发邮件 1280253714qq.com 原…

Go语言入门心法(一): 基础语法

Go语言入门心法(一) Go语言入门心法(二): 结构体 Go语言入门心法(三): 接口 Go语言入门心法(四): 异常体系 Go语言入门心法(五): 函数 一: go语言中变量认知 go语言中变量的定义: &#xff08;要想飞|先会走&#xff09;||&#xff08;翻身仗|抹遗憾 &#xff09; |&…

基于IDEA集成环境---Nacos安装

Nacos服务器是独立安装部署的&#xff0c;因此我们需要下载最新的Nacos服务端程序&#xff0c;下载地址&#xff1a;https://github.com/alibaba/nacos。 将文件进行解压&#xff0c;得到以下内容&#xff1a; 直接将其拖入到项目文件夹下&#xff0c;便于我们一会在IDEA内部…

mysql case when 不命中缓存

case when 在sql 中非常方便数据不同维度统计&#xff0c;但是也会出现mysql 索引不命中问题&#xff0c;当多个case 出现时&#xff0c;需要提取出来到where里面优化 优化后 SELECT date(RecordTime) AS date, count( DISTINCT CASE WHEN Param 1 …

什么是美体SDK?美摄美颜美体SDK对接开发指南

在当今的数字世界中&#xff0c;人们对自我表达和形象展示的需求越来越高。美体SDK应运而生&#xff0c;为用户提供了一种全新的美颜美体体验&#xff0c;让每一个人都能享受到个性化的美丽与自信。 一、美体SDK的特点 轻量级&#xff1a;美体SDK体积小巧&#xff0c;不会对用…

运用精益管理思想提升MES管理系统建设水平

随着制造业的不断发展&#xff0c;MES生产管理系统已经成为了企业生产过程中不可或缺的一部分。而在MES管理系统建设过程中&#xff0c;精益管理的思想也越来越受到重视。本文将探讨如何运用精益管理的思想&#xff0c;提高MES系统的建设水平&#xff0c;以更好地服务于企业的生…

Sanic​——Python函数变成API的神器

今天给大家介绍一个超好用的框架&#xff0c;迅速将Python函数变成API&#xff0c;它就是最近越来越火的异步Web框架Sanic。 1. Sanic简介 Sanic 是 Python3.7 Web 服务器和 Web 框架&#xff0c;旨在提高性能。它允许使用 Python3.5 中添加的async/await语法&#xff0c;这使…

1.Vue-在独立页面实现Vue的增删改查

题记 在独立页面实现Vue的增删改查&#xff0c;以下是具体的代码&#xff0c;和操作流程。 编写index.html页面 index.html文件如下&#xff1a; <!DOCTYPE html> <html> <head><title>Vue CRUD Example</title><!--在线导入vue文件-->&l…

Linux系统之ip命令的基本使用

Linux系统之ip命令的基本使用 一、ip命令介绍1.1 ip命令简介1.2 ip命令的由来1.3 ip命令的安装包 二、ip命令使用帮助2.1 ip命令的help帮助信息2.2 ip命令使用帮助 三、查看网络信息3.1 显示当前网络接口信息3.2 显示网络设备运行状态3.3 显示详细设备信息3.4 查看路由表3.5 查…