算法训练营 day24 回溯算法 回溯算法理论基础 组合

news2024/12/25 9:30:34

算法训练营 day24 回溯算法 回溯算法理论基础 组合

回溯算法理论基础

回溯法也可以叫做回溯搜索法,它是一种搜索的方式。

虽然回溯法很难,很不好理解,但是回溯法并不是什么高效的算法

因为回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案

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

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 棋盘问题:N皇后,解数独等等

回溯法解决的问题都可以抽象为树形结构,是的,我指的是所有回溯法的问题都可以抽象为树形结构!

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

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

在这里插入图片描述

回溯三部曲

  • 回溯函数模板返回值以及参数

  • 回溯函数终止条件

  • 回溯搜索的遍历过程

回溯算法模板框架如下:

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

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

组合

77. 组合 - 力扣(LeetCode)

给定两个整数 nk,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

  • 递归函数的返回值以及参数

在这里要定义两个全局变量,一个用来存放符合条件单一结果,一个用来存放符合条件结果的集合。

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

从下图中红线部分可以看出,在集合[1,2,3,4]取1之后,下一层递归,就要在[2,3,4]中取数了,那么下一层递归如何知道从[2,3,4]中取数呢,靠的就是startIndex。

在这里插入图片描述

所以需要startIndex来记录下一层递归,搜索的起始位置。

那么整体代码如下:

 List<List<Integer>> result = new ArrayList<List<Integer>>();
 List<Integer> path = new ArrayList<Integer>();
 void backtracking(int n, int k, int startIndex)
  • 回溯函数终止条件

path这个数组的大小如果达到k,说明我们找到了一个子集大小为k的组合了,在图中path存的就是根节点到叶子节点的路径。

if (path.size()==k){
    result.add(path);
    return;
}
  • 单层搜索的过程

for循环每次从startIndex开始遍历,然后用path保存取到的节点i。

代码如下:

for (int i = startIndex; i <= n; i++) { // 控制树的横向遍历
    path.add(i); // 处理节点 
    backtracking(n, k, i + 1); // 递归:控制树的纵向遍历,注意下一层搜索要从i+1开始
    path.remove(path.size()-1); // 回溯,撤销处理的节点
}

java整体代码如下:

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

优化剪枝

在这里插入图片描述

所以,可以剪枝的地方就在递归中每一层的for循环所选择的起始位置

如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了

接下来看一下优化过程如下:

  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。

从2开始搜索都是合理的,可以是组合[2, 3, 4]。

优化后代码:

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

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

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

相关文章

钉钉微应用 - - - - 如何本地开发调试?

钉钉微应用 - 本地开发调试1. 安装DingTalk-Design-CLI2. 初始化代码模版3. 启动开发、调试功能4. 遇到的问题4.1 对应企业没有xxx域名微应用&#xff1f;&#xff1f;4.2 history、location的表现异常&#xff1f;&#xff1f;4.3 本地已经存在了H5微应用&#xff0c;也想使用…

软件体系结构与架构技术知识点万字总结

文章目录页面技术一、Spring框架1. 三层体系架构2. Spring的核心3. Spring 的Bean中主要的装配方式&#xff08;1&#xff09;基于XML的装配&#xff1a;&#xff08;2&#xff09;基于Annotation的装配&#xff1a;&#xff08;3&#xff09;自动装配&#xff1a;4. Spring框架…

Linux 中启用 SSH 密码登录

Linux 中启用 SSH 密码登录 文章目录Linux 中启用 SSH 密码登录1、更改配置文件2、设置登录密码3、完成1、更改配置文件 首先使用 管理员 权限打开/etc/ssh/sshd_config文件。 sudo vi /etc/ssh/sshd_config找到 PasswordAuthentication 选项&#xff0c;耐心查找。 当然&am…

23种设计模式之十一种行为型模式

23种设计模式之十一种行为型模式1. 设计模式概述1.1 什么是设计模式1.2 设计模式的好处2. 设计原则分类3. 详解3.1 单一职责原则3.2 开闭原则3.3 里氏代换原则3.4 依赖倒转原则3.5 接口隔离原则3.6 合成复用原则3.7 迪米特法则4. Awakening1. 设计模式概述 我们的软件开发技术也…

车道线检测源码详解

源码链接见文末 1.车道数据与标签下载 数据下载地址:因为数据的规模比较大,源码中只包含了部分数据,能够供运行代码使用 CULane:https://xingangpan.github.io/projects/CULane.html tusimple:https://github.com/TuSimple/tusimple-benchmark/issues/3 2.项目环境配置 …

数据存储:MySQL之多表连接方式

在我们走出新手村&#xff0c;开始编写系统时&#xff0c;总会遇到各种复杂的场景需要多个数据库表的联查&#xff0c;这时我们就需要掌握多表查询有几种方式&#xff0c;以便我们在各种复杂的应用场景使用适宜的连接方式。 用于测试的表&#xff1a; student表 grade表 syst…

车载以太网 - SomeIP测试专栏 - 详细解析 - 02

对于介绍SomeIP协议&#xff0c;我还是想从最基础的协议解析来&#xff0c;所以今天还是先将SomeIP协议详解给大家列举一下&#xff0c;也方便大家在工作中如果不记得哪些信息随时可以查看学习&#xff0c;也算是留给我自己的笔记吧&#xff0c;毕竟确实容易忘记。 SomeIP数据&…

【GD32F427开发板试用】基于移植BP神经网络辨认花的种类

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;卢瑟 前言 很荣幸参与这次GD32的开发板试用活动(白嫖活动)&#xff0c;由于在家条件比较有限&#xff0c;就移植了之前做过的项目。利用神经网…

【Java开发常用软件整理】

该博客整理了一些JAVA程序员常用的软件开发类软件、系统类软件&#xff0c;可以作为JAVA程序员配置Java开发基础环境的参考手册。 目录开发类软件Java8 安装IntelliJ IDEA 安装Maven 安装Git 安装MYSQL 安装系统类软件开发类软件 开发软件安装包下载地址&#xff1a;开发软件安…

ASP.NET Core Web应用程序项目部署流程

目录 一、准备ASP.NET Core应用程序部署文件 二、环境配置 三、测试 ASP.NET Core Web 应用程序 四、部署后访问失败问题 以下部署流程都是基于Windows服务器环境下进行的。 一、准备ASP.NET Core应用程序部署文件 使用 Visual Studio 开发工具创建 ASP.NET Core 的Web应…

盘点最近线程池的几个面试重要考点

有点惊叹最近的面试题&#xff0c;因为从之前的基础的面试题&#xff0c;到之后的一些涉及到分布式和微服务的面试题&#xff0c;再到现在的线程池的一些面试题&#xff0c;反正不同的面试官&#xff0c;就有不同的针对方向&#xff0c;可能现在的面试官比较想考验你的多方面的…

Hive(2):Apache Hive 安装部署

1 元数据相关名词 1.1 Metadata Metadata即元数据。元数据包含用Hive创建的database、table、表的位置、类型、属性&#xff0c;字段顺序类型等元信息。元数据存储在关系型数据库中。如hive内置的Derby、或者第三方如MySQL等。 1.2 Metastore Metastore即元数据服务。Metast…

Python中tqdm进度条的详细介绍(安装程序与耗时的迭代)

平时在做一些测试时候&#xff0c;是没有进度条出现的&#xff0c;这跟大家pip安装程序不一样(有安装进度条)&#xff0c;比如做遍历的时候&#xff1a;for i in range(10):time.sleep(0.5)print(i)只是每过0.5秒就进行打印输出&#xff0c;在这个等待过程是没有任何提示的&…

SAP ADM100-2.1 SAP系统启停过程

一、SAP系统开启过程 在SAP系统使用过程中维护硬件和修改SAP系统配置文件后重启SAP系统是有必要的。开启SAP系统是每个SAP系统管理员应该熟悉的初始过程。 每个SAP系统包含一个数据库和至少一个实例,JAVA栈SAP系统还有一个CS中央服务实例,ABAP栈SAP系统含有一个ABAP CS中央服…

springboot2.5集成log4j2报错

报错信息&#xff1a; SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. 修改依赖 把依…

【01Studio MaixPy AI K210】22.ESP8266与服务器连接的问题及处理

目录 前提 问题 处理 前提 WiFi的账号密码输入正确 ESP8266的主题与服务器的主题一致 代码的服务器网址正确 ESP8266正确连接核心板的引脚 ESP8266返回“OK” simple.py文件以发送到开发板 WiFi已打开 问题 1.连接上WiFi&#xff0c;已输出IP信息&#xff0c;但是仍然…

48.Isaac教程--GMapping应用程序

GMapping应用程序 GMapping 是一个使用 OpenSlam 软件库的地图生成工具。 该应用程序允许您创建地图以在其他应用程序中使用。 GMapping 应用程序使用 Carter 参考机器人的 LIDAR 功能。 注意 建图是一项计算密集型和存储密集型活动&#xff0c;可能需要微调才能生成合适的…

Hive(1):Apache Hive入门

1 Apache Hive概述 1.1 什么是Hive Apache Hive是一款建立在Hadoop之上的开源数据仓库系统&#xff0c;可以将存储在Hadoop文件中的结构化、半结构化数据文件映射为一张数据库表&#xff0c;基于表提供了一种类似SQL的查询模型&#xff0c;称为Hive查询语言&#xff08;HQL&a…

记OPNsense防火墙的安装过程 - 安全

前些天在网上看到防火墙软件OPNsense&#xff0c;对其有了兴趣&#xff0c;以前写过一个其前面的一个软件M0n0wall( 关于m0n0wall的安装及配置 )&#xff0c;当时也是非常有名的防火墙&#xff0c;现在有了OPNsense&#xff0c;这个老防火墙已经停止更新了。 下面对OPNsense防火…

MFC如何实现屏幕截图

目录一 程序实现效果二 程序实现思路三 具体实现一 程序实现效果 本文描述了MFC中实现屏幕截图的一种方式&#xff0c;程序界面如下&#xff1a; 单击【开始截屏】&#xff0c;按住鼠标左键&#xff0c;一直拖动到需要截屏的矩形的右下角&#xff0c;松开鼠标左键&#xff0c…