图解 LeetCode 算法汇总——回溯

本文首发公众号:小码A梦

回溯算法是一种常见的算法,常见用于解决排列组合、排列问题、搜索问题等算法,在一个搜索空间中寻找所有的可能的解。通过向分支不断尝试获取所有的解,然后找到合适的解,找完一个分支后再往回搜索。回溯算法通常使用递归的方式实现。

回溯本质是一种暴力搜索法,列出所有可能的解,然后找到合适的解。以 a、b、c的排列组合为例,画出全排列组合。

以上排列组合回溯步骤:

  • 列出所有可能存在的组合。
  • 分解组合,把问题分解多个阶段,每个阶段添加一个分叉。
  • 走完一个分叉,或者遇到不符合期望条件的时,就退回到上一个分叉。继续走其它没走的路。直到走完所有的路。
  • 回溯一半都是使用递归实现。

根据以上的步骤得出一个简单的回溯算法的模板:

public Solution {List<List<Integer>> result;LinkedList<Integer> path;//记录那些元素被遍历过boolean[] used;private List<List<Integer>> permute(int[] nums) {result = new ArrayList<>();path = new LinkedList<>();used = new boolean[nums.length];permuteHelper(nums);return result;}private void permuteHelper(int[] nums) {if (递归终止条件) {result.add(new ArrayList<>(path));return;}//遍历各个元素for (int i = 0; i < nums.length; i++) {used[i] = true;//选择元素path.add(nums[i]);permuteHelper(nums);//移除元素path.removeLast();used[i] = false;}}
}

以上代码使用递归,递归一般要设置一个终止条件,然后遍历整个元素,通过链表选择元素和移除元素。

LeetCode 题解

上面所说的,回溯主要解决一些排列组合、排列问题、搜索问题等问题,LeetCode 有很多类似的问题,这里选取了几个比较常见的题目。

  • 39 组合总和
  • 40 组合总和 II
  • 46 全排列
  • 47 全排列 II
  • 51 N皇后

39.组合总和(中等)

题目描述

解法

这是一个比较典型的排列组合问题,本题采用的是求总和,使用总和减去遍历的数据,最后得到结果为零,就是符合的组合。

  • 为了减少遍历次数,数组需要先排序。总数减的数据如果小于零,就不会在该分支继续遍历了。
  • 可以重复使用元素,每次都遍历一遍全部元素。
  • 减去分支结果之后,以新的结果,再创建分支做减法。
  • 递归遍历一直到结果为零和负数。
    • 为零,符合条件,记录数据,对应的分支遍历终止,继续遍历下一个分支。
    • 为负数,返回到上一个分支,继续遍历后面的分支。

最终代码:

class Solution {List<List<Integer>> list = new ArrayList<>();int[] candidate;public List<List<Integer>> combinationSum(int[] candidates, int target) {Arrays.sort(candidates);candidate = candidates;recall(0,target,new LinkedList<>());return list;}private void recall(int start, int target, LinkedList<Integer> path) {if (target == 0) {list.add(new ArrayList<>(path));return;}for (int i = start; i <candidate.length ; i++) {int sub = target - candidate[i];if (sub < 0) {break;}path.add(candidate[i]);recall(i,sub,path);path.removeLast();}}
}

recall 使用递归方法遍历分支,而使用链表的特性,记录遍历的节点,如果不符合要求就上一个分支回撤,同时链表移除最后一个结点。

40.组合总和II(中等)

解题思路

这题的解题思路和上面的组合总和是差不多的,唯一不同的是元素不能被重复遍历,使用一个变量记录遍历的起始值,遍历过的数据,下次往后一位开始遍历。

代码如下:

class Solution {List<List<Integer>> list = new ArrayList<>();int[] candidate;public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);candidate = candidates;recall(0,target,new LinkedList<>());return list;}private void recall(int start, int target, LinkedList<Integer> path) {if (target == 0) {list.add(new ArrayList<>(path));return;}for (int i = start; i <candidate.length ; i++) {//这里解决集合重复问题 if (i > start && candidate[i] == candidate[i-1]) {continue;}int sub = target - candidate[i];if (sub < 0) {break;}path.add(candidate[i]);recall(i + 1,sub,path);path.removeLast();}}
}

start 记录遍历的起始值,其他解题方法和上面的组合求和是类似的。题目还有一个要求是不能出现重复的组合,就需要判断 candidate[i] == candidate[i-1] 就忽略该数据,往后继续遍历。

46.全排列

解题思路

  • 每个元素都需要遍历一遍。
  • 遍历元素的时,遍历完第一数,继续遍历未遍历的数据。
  • 遍历结束后,返回上一个分叉。

代码整理如下:

class Solution {List<List<Integer>> result = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();boolean[] used;public List<List<Integer>> permute(int[] nums) {if (nums.length == 0) {return result;}used = new boolean[nums.length];permuteHelper(nums);return result;}private void permuteHelper(int[] nums) {if (path.size() == nums.length) {result.add(new ArrayList<>(path));return;}for (int i = 0; i < nums.length; i++) {if (used[i]) {continue;}used[i] = true;path.add(nums[i]);permuteHelper(nums);path.removeLast();used[i] = false;}}
}

使用 used 记录哪些数据遍历过,遍历过的数据不会遍历,其他也是使用递归搜索。

51.N皇后

题目描述

解题思路

N 皇后问题是一个经典的回溯算法问题,是面试比较常见的问题。在一个 n * n 的棋盘上,每个格子放入的元素后,查看是够有同行、同列、左上方以及右上方是否冲突,冲突就回溯,不冲突就继续往下遍历。

  • 初始化数组,默认初始值。
  • 每一行只能放一个 Q,不冲突后,再遍历下一列的数据(因为同一行不能冲突)。
  • 因为每一行只放一个 Q,所以不存在同行冲突。判断冲突就潘丹同一列、左上方以及右上方是否有冲突。
  • 遍历到最后一行时,记录符合条件的数据。
class Solution {List<List<String>> res = new ArrayList<>();public List<List<String>> solveNQueens(int n) {// 初始化棋盘 "." 表示空,"Q"表示皇后,char[][] board = new char[n][n];for (char[] c : board) {Arrays.fill(c, '.');}backtrack(board, 0);return res;}private void backtrack(char[][] board, int row) {//终止条件if (row == board.length) {res.add(charToList(board));return;}//每一行列数(也就是长度)int n = board[row].length;for (int col = 0; col < n; col++) {//排除相互攻击的格子if (!isValid(board,row,col)) {continue;}//放入Qboard[row][col] = 'Q';//进入下一行放皇后backtrack(board,row + 1);//撤销Qboard[row][col] = '.';}}private boolean isValid(char[][] board, int row, int col) {int n = board.length;//检查列是否有皇后冲突for (int i = 0; i < n; i++) {if (board[i][col] == 'Q') {return false;}}//检查右上方是否有皇后冲突for (int i = row - 1,j = col + 1; i >= 0 && j < n; i--,j++) {if (board[i][j] == 'Q') {return false;}}//检查左上方是否有皇后冲突for (int i = row - 1,j = col - 1; i >= 0 && j >= 0; i--,j--) {if (board[i][j] == 'Q') {return false;}}return true;}public List<String> charToList(char[][] board) {List<String> list = new ArrayList<>();for (int i = 0; i < board.length; i++) {list.add(String.copyValueOf(board[i]));}return list;}
}

总结

回溯算法尝试在问题的解空间中搜索可能的解,并在搜索过程中进行选择、撤销选择和终止搜索,直到找到解或确定无解为止。

  • 通常通过递归函数来实现回溯算法。
  • 在每一步,需要做出选择(选择一个分支)然后递归地探索该选择的结果。
  • 在递归返回后,需要撤销之前的选择,以便继续探索其他分支。
  • 使用条件语句或循环来控制选择的范围和条件。

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

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

相关文章

NLP(4)--BERT

目录 一、自监督学习 二、BERT的两个问题 三、GLUE 四、BERT与Transformer的关系 五、BERT的训练方式 六、BERT的四个例子 1、语句分类&#xff08;情感分析&#xff09; 2、词性标注 3、立场分析 4、问答系统 七、BERT的后续 1、为什么预训练后的微调可以满足多…

北京互联网营销服务商浩希数字科技申请1350万美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于北京的互联网营销服务商浩希数字科技&#xff08;Haoxi Health Technology Limited &#xff09;近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯…

08-JVM垃圾收集器详解

上一篇&#xff1a;07-垃圾收集算法详解 如果说收集算法是内存回收的方法论&#xff0c;那么垃圾收集器就是内存回收的具体实现。 虽然我们对各个收集器进行比较&#xff0c;但并非为了挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现&#xff0c;更加没…

vue学习之条件渲染

条件渲染 用于控制组件显示创建 demo6.html,内容如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…

JavaScript-----jQuery

目录 前言&#xff1a; 1. jQuery介绍 2. 工厂函数 - $() jQuery通过选择器获取元素&#xff0c;$("选择器") 过滤选择器&#xff0c;需要结合其他选择器使用。 3.操作元素内容 4. 操作标签属性 5. 操作标签样式 6. 元素的创建,添加,删除 7.数据与对象遍历…

vue学习之事件绑定

事件绑定 创建 demo5.html,内容如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</…

jupyter 添加中文选项

文章目录 jupyter 添加中文选项1. 下载中文包2. 选择中文重新加载一下&#xff0c;页面就变成中文了 jupyter 添加中文选项 1. 下载中文包 pip install jupyterlab-language-pack-zh-CN2. 选择中文 重新加载一下&#xff0c;页面就变成中文了 这才是设置中文的正解&#xff…

目标检测笔记(十五): 使用YOLOX完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)

文章目录 一、目标检测介绍二、YOLOX介绍三、源码获取四、环境搭建4.1 环境检测 五、数据集准备六、模型训练七、模型验证八、模型测试 一、目标检测介绍 目标检测&#xff08;Object Detection&#xff09;是计算机视觉领域的一项重要技术&#xff0c;旨在识别图像或视频中的…

Jmeter进阶使用指南-使用参数化

Apache JMeter是一个广泛使用的开源负载和性能测试工具。在进行性能测试时&#xff0c;我们经常需要模拟不同的用户行为和数据&#xff0c;这时候&#xff0c;参数化就显得尤为重要。此文主要介绍如何在JMeter中使用参数化。 什么是参数化&#xff1f; 参数化是一种将静态值替…

注意力机制讲解与代码解析

一、SEBlock(通道注意力机制) 先在H*W维度进行压缩&#xff0c;全局平均池化将每个通道平均为一个值。 &#xff08;B, C, H, W&#xff09;---- (B, C, 1, 1) 利用各channel维度的相关性计算权重 (B, C, 1, 1) --- (B, C//K, 1, 1) --- (B, C, 1, 1) --- sigmoid 与原特征相…

Ubuntu终端指令

目录 目录 一、基本指令 1.命令行提示符 2.切换用户 3.修改密码 4.查看当前目录下的文件 5.修改文件权限---chmod 6.cd 切换路径 7.touch 8.cat 9.echo 10.mkdir 11. rm/rmdir 二、在线下载软件 1.更新软件源 2.更新软件列表 3.下载软件 三、离线安装软件 1. …

ansible搭建

一&#xff0c;ansible是一种由Python开发的自动化运维工具&#xff0c;集合了众多运维工具&#xff08;puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置、批量程序部署、批量运行命令等功能 二&#xff0c;特点 * 部署简单 * **默认…

Docker:01 OverView

Docker&#xff1a;01 OverView 基本介绍 Docker是一个用于开发、交付、运行应用程序的开放平台&#xff0c;可以使应用程序与基础架构分开&#xff0c;以便快速交付软件。 Docker在一个被叫做容器的隔离环境下&#xff0c;提供了打包和运行的能力。 容器非常轻量化&#x…

时序分解 | MATLAB实现基于小波分解信号分解分量可视化

时序分解 | MATLAB实现基于小波分解信号分解分量可视化 目录 时序分解 | MATLAB实现基于小波分解信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于小波分解的分量可视化&#xff0c;MATLAB编程程序&#xff0c;用于将信号分解成不同尺度和频率的子信…

ARM DIY(十一)板子名称、开机 logo、LCD 控制台、console 免登录、命令提示符、文件系统大小

文章目录 前言板子名称uboot Modelkernel 欢迎词、主机名 开机 logoLCD 控制台console 免登录命令提示符文件系统大小 前言 经过前面十篇文章的介绍&#xff0c;硬件部分调试基本完毕&#xff0c;接下来的文章开始介绍软件的个性化开发。 板子名称 uboot Model 既然是自己的…

云备份——服务端客户端联合测试

一&#xff0c;准备工作 服务端清空备份文件信息、备份文件夹、压缩文件夹 客户端清空备份文件夹 二&#xff0c;开始测试 服务端配置文件 先启动服务端和客户端 向客户端指定文件夹放入稍微大点的文件&#xff0c;方便后续测试断点重传 2.1 上传功能测试 客户端自动上传成功…

【FPGA】通俗理解从VGA显示到HDMI显示

注&#xff1a;大部分参考内容来自“征途Pro《FPGA Verilog开发实战指南——基于Altera EP4CE10》2021.7.10&#xff08;上&#xff09;” 贴个下载地址&#xff1a; 野火FPGA-Altera-EP4CE10征途开发板_核心板 — 野火产品资料下载中心 文档 hdmi显示器驱动设计与验证 — …

《服务器无状态设计:为什么如何实现无状态API?》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

高速路自动驾驶功能HWP功能定义

一、功能定义 高速路自动驾驶功能HWP是指在一般畅通高速公路或城市快速路上驾驶员可以放开双手双脚&#xff0c;同时注意力可在较长时间内从驾驶环境中转移&#xff0c;做一些诸如看手机、接电话、看风景等活动&#xff0c;该系统最低工作速度为60kph。 如上两种不同环境和速度…

你参与的APP开发项目安全吗?

Android将安全设计贯穿系统架构的各个层面&#xff0c;覆盖系统内核、虚拟机、应用程序框架层以及应用层各个环节&#xff0c;力求在开放的同时&#xff0c;也恰当保护用户的数据、应用程序和设备的安全。Android安全模型主要提供以下几种安全机制&#xff1a; 进程沙箱隔离机…