当前位置: 首页 > news >正文

【递归与回溯深度解析:经典题解精讲(中篇)】—— LeetCode

文章目录

  • 组合
  • 目标和
  • 组合总和
  • 字母大小写全排序
  • 优美的排列
  • N皇后

组合

在这里插入图片描述
思路:回溯算法

  • 问题要求从 1 到 n 中选出 k 个数的所有组合。
    使用回溯算法递归构造解。
    每次递归时,记录当前的组合路径,当组合长度达到 k 时,将其加入结果集。
    剪枝优化:在递归过程中,如果当前选择的起点到 n 不够 k 个数,就停止递归。
class Solution 
{vector<vector<int>> ret; // 用于存储最终的所有组合结果vector<int> path;        // 用于存储当前正在构建的组合int n, k;                // n 表示范围 [1, n],k 表示组合的大小public:vector<vector<int>> combine(int _n, int _k) {n = _n; // 初始化 nk = _k; // 初始化 kdfs(1); // 从数字 1 开始进行深度优先搜索return ret; // 返回所有的组合结果}// 深度优先搜索函数,用于生成所有的组合void dfs(int pos){// 如果当前组合的大小等于 k,则将该组合加入结果集if(k == path.size()){ret.push_back(path); // 将当前组合存储到结果集中return; // 返回,结束当前递归分支}// 从当前数字 pos 开始,尝试加入到组合中for(int i = pos; i <= n; i++){path.push_back(i); // 将当前数字加入到组合中dfs(i + 1);        // 递归调用,处理下一个数字,确保数字不会重复path.pop_back();   // 回溯:移除最后加入的数字,尝试其他可能性}}
};

目标和

在这里插入图片描述
回溯:

  • 通过正负号的分配来形成目标和,尝试所有可能的组合。
    如果找到一种方式满足条件,计数+1。
class Solution 
{int ret, aim; // `ret` 用于存储满足条件的方案总数,`aim` 是目标值public:int findTargetSumWays(vector<int>& nums, int target) {aim = target; // 初始化目标值ret = 0;      // 初始化方案数dfs(nums, 0, 0); // 从索引 0 开始递归搜索,初始路径和为 0return ret;    // 返回满足条件的方案数}// 深度优先搜索函数,用于枚举所有可能的路径和void dfs(vector<int>& nums, int pos, int path){// 如果已经遍历到数组末尾,检查路径和是否等于目标值if(pos == nums.size()){if(path == aim) ret++; // 如果路径和等于目标值,则方案数加 1return; // 返回,结束当前递归分支}// 选择将当前数字加到路径和dfs(nums, pos + 1, path + nums[pos]);// 选择将当前数字减到路径和dfs(nums, pos + 1, path - nums[pos]);}
};

组合总和

在这里插入图片描述
思路:回溯算法

  • 使用回溯方法,试图从给定的数字中选出若干个数(可重复)使其和为目标值。
    在递归过程中:
    当前路径的总和如果大于目标值,停止搜索。
    如果总和等于目标值,将当前路径加入结果。
    每次递归时从当前数字开始,避免重复路径。
class Solution 
{int aim;                     // 目标和vector<vector<int>> ret;     // 存储所有满足条件的组合vector<int> path;            // 存储当前路径(正在构建的组合)public:vector<vector<int>> combinationSum(vector<int>& nums, int target) {aim = target;            // 设置目标和dfs(nums, 0, 0);         // 从索引 0 开始深度优先搜索,当前和为 0return ret;              // 返回所有符合条件的组合}// 深度优先搜索函数void dfs(vector<int>& nums, int pos, int sum){// 如果当前和等于目标值,将当前组合加入结果集if(sum == aim){ret.push_back(path); // 将当前路径(组合)存入结果集return;              // 返回,结束当前递归分支}// 如果当前和超过目标值,或索引超出数组范围,则返回if(sum > aim || pos == nums.size()) return;// 从当前索引 `pos` 开始,尝试每个数字for(int i = pos; i < nums.size(); i++){path.push_back(nums[i]);        // 将当前数字加入到路径中dfs(nums, i, sum + nums[i]);   // 递归调用,允许重复选择当前数字path.pop_back();               // 回溯:移除最后一个加入的数字,尝试其他可能性}}
};

字母大小写全排序

在这里插入图片描述
思路:回溯算法

  • 遍历字符串,每遇到一个字母字符,就有两种选择(小写或大写)。
    使用递归构造所有可能的字符串路径:
    对于每个字符,选择原字符或大小写转换后的字符加入路径。
    遇到数字时,直接加入路径。
    当遍历到字符串末尾时,将路径加入结果集。
class Solution 
{vector<string> ret; // 用于存储所有满足条件的字符串组合string path;        // 当前正在构建的路径(部分字符串)public:vector<string> letterCasePermutation(string s) {dfs(s, 0); // 从字符串的第 0 个字符开始深度优先搜索return ret; // 返回所有可能的组合结果}// 深度优先搜索函数void dfs(string& s, int pos){// 如果当前处理位置等于字符串长度,说明路径构造完成if(pos == s.size()){ret.push_back(path); // 将路径加入结果集return;              // 返回,结束当前递归分支}char ch = s[pos];// 情况 1:不改变当前字符,直接加入路径path.push_back(ch);dfs(s, pos + 1); // 递归处理下一个字符path.pop_back(); // 回溯,移除当前字符// 情况 2:改变当前字符的大小写if(ch < '0' || ch > '9') // 如果当前字符不是数字,尝试改变大小写{char tmp = change(ch); // 改变字符大小写path.push_back(tmp);   // 将改变后的字符加入路径dfs(s, pos + 1);       // 递归处理下一个字符path.pop_back();       // 回溯,移除改变后的字符}}// 辅助函数:改变字符的大小写char change(char ch){if(ch <= 'z' && ch >= 'a') ch -= 32; // 小写转大写else ch += 32;                       // 大写转小写return ch;}
};

优美的排列

在这里插入图片描述
思路:回溯+剪枝

  • 使用回溯法,尝试将数字放入数组中。
    每次递归时,判断当前数字是否满足条件(能被当前位置整除或能整除当前位置)。
    剪枝优化:如果当前排列不符合条件,提前停止递归。
class Solution 
{int ret;              // 用于记录满足条件的排列方案数bool check[16];       // 用于记录数字是否被使用过(数组下标从 1 开始)public:int countArrangement(int n) {dfs(n, 1);        // 从位置 1 开始深度优先搜索return ret;       // 返回最终的方案数}// 深度优先搜索函数void dfs(int n, int pos){// 递归终止条件:如果当前位置超出 n,说明排列完成if(pos == n + 1){ret++;        // 当前排列满足条件,计数加 1return;       // 返回,结束当前递归分支}// 尝试将每个数字放在当前的位置for(int i = 1; i <= n; i++){// 如果数字 i 尚未被使用,且满足题目中的条件if(!check[i] && (pos % i == 0 || i % pos == 0)){check[i] = true;    // 标记数字 i 已被使用dfs(n, pos + 1);    // 递归处理下一个位置check[i] = false;   // 回溯:取消数字 i 的使用状态}}}
};

N皇后

在这里插入图片描述
思路:回溯+剪枝

  • 使用回溯法尝试将 N 个皇后放置到 N×N 棋盘上。
    在递归过程中,每一行尝试放置一个皇后:
    检查当前列、主对角线、副对角线是否已被占用。
    剪枝优化:利用标志数组记录列、主对角线、副对角线是否被占用,避免重复检查。
    当所有行都放置完成时,将当前结果加入结果集。
class Solution 
{bool checkCol[10], checkdig1[20], checkdig2[20]; // 分别记录列、主对角线、副对角线是否被占用vector<vector<string>> ret; // 存储所有符合条件的棋盘配置vector<string> path;        // 当前棋盘状态int n;                      // 棋盘的大小public:vector<vector<string>> solveNQueens(int _n) {n = _n;                  // 初始化棋盘大小path.resize(n);          // 初始化棋盘状态for(int i = 0; i < n; i++)path[i].append(n, '.'); // 将每一行初始化为 `n` 个 '.'(表示空位置)dfs(0);                  // 从第 0 行开始深度优先搜索return ret;              // 返回所有符合条件的棋盘配置}// 深度优先搜索函数void dfs(int row){// 递归终止条件:如果已经处理到第 n 行,说明所有皇后都已放置完成if(row == n){ret.push_back(path); // 将当前棋盘状态加入结果集return;              // 返回,结束当前递归分支}// 遍历当前行的每一列,尝试放置皇后for(int col = 0; col < n; col++){// 检查当前列、主对角线、副对角线是否被占用if(!checkCol[col] && !checkdig1[row - col + n] && !checkdig2[row + col]){// 放置皇后,更新棋盘状态和限制条件path[row][col] = 'Q';                             // 在 (row, col) 放置皇后checkCol[col] = checkdig1[row - col + n] = checkdig2[row + col] = true; // 标记当前位置dfs(row + 1); // 递归处理下一行// 回溯:移除皇后,恢复棋盘状态和限制条件path[row][col] = '.';                             // 移除 (row, col) 的皇后checkCol[col] = checkdig1[row - col + n] = checkdig2[row + col] = false; // 取消标记}}}
};

相关文章:

【递归与回溯深度解析:经典题解精讲(中篇)】—— LeetCode

文章目录 组合目标和组合总和字母大小写全排序优美的排列N皇后 组合 思路&#xff1a;回溯算法 问题要求从 1 到 n 中选出 k 个数的所有组合。 使用回溯算法递归构造解。 每次递归时&#xff0c;记录当前的组合路径&#xff0c;当组合长度达到 k 时&#xff0c;将其加入结果集…...

01.HTTPS的实现原理-HTTPS的概念

01.HTTPS的实现原理-HTTPS的概念 简介1. HTTPS的概念和安全性2. HTTPS的实现原理3. HTTPS和HTTP的区别4. OSI七层协议模型5. SSL和TLS的区别 简介 该系列文章主要讲述了HTTPS协议与HTTP协议的区别&#xff0c;以及HTTPS如何实现安全传输。内容分为三部分&#xff1a;HTTPS的实…...

一文详解MacOS+CLion——构建libtorch机器学习开发环境

对于希望在本地环境中进行深度学习开发的开发者来说&#xff0c;配置合适的工具链是至关重要的一步。本文旨在帮助您在 macOS 操作系统上&#xff0c;利用 CLion IDE 和 PyTorch 的 C依赖库——libtorch&#xff0c;快速搭建起一个高效的开发环境。这里我们将一步步地讲解如何下…...

【LeetCode 面试经典150题】详细题解之哈希表篇

【LeetCode 面试经典150题】详细题解之哈希表篇 1 哈希表的基础1.1 基础概念及实现1.2.1 哈希表的工作原理1.2.2 705.设计哈希集合1.2.3 706.设计哈希映射 1.2 HashMap相关1.2.1 基本操作1.2.2 遍历 1.3 Hashtable1.4 LinkedHashMap1.5 HashSet**1.5.1基本特性**1.5.2 基本方法…...

linux socket编程之udp_dict_serve服务端--引入配置文件

注意&#xff1a;本篇博客只是对上一篇博客功能的增加 1.创建配置文件(翻译) Dict.txt apple: 苹果 banana: 香蕉 cat: 猫 dog: 狗 book: 书 pen: 笔 happy: 快乐的 sad: 悲伤的 run: 跑 jump: 跳 teacher: 老师 student: 学生 car: 汽车 bus: 公交车 love: 爱 hate: 恨 hell…...

selenium学习笔记(二)

文章目录 前言设计模式POMPOM概念POM优势POM设计原则POM的实现 selenium的常用操作处理动态元素截图操作勾选复选框多层框架/窗口定位操作下拉框上传文件操作处理弹窗切换窗口拖拽操作 如何处理浏览器驱动更新导致的问题selenium与网站监控监听网页内容变化监控网络请求 seleni…...

宏集eX710物联网工控屏在石油开采机械中的应用与优势

案例概况 客户&#xff1a;天津某石油机械公司 应用产品&#xff1a;宏集eX710物联网工控屏 应用场景&#xff1a;钻井平台设备控制系统 一、应用背景 石油开采和生产过程复杂&#xff0c;涵盖钻井平台、采油设备、压缩机、分离器、管道输送系统等多种机械设备。这些设备通…...

linux——vi命令常用操作

一、vi模式 vi一般分为三种模式&#xff0c;分别是命令行模式、插入模式、末行模式 1.命令模式&#xff1a;控制屏幕光标的移动&#xff0c;按 &#xff1a;进入末行模式&#xff0c;按 i&#xff08;其他插入命令也可&#xff09; 进入插入模式&#xff1b; 2.插入模式&…...

vscode添加全局宏定义

利用vscode编辑代码时&#xff0c;设置了禁用非活动区域着色后&#xff0c;在一些编译脚本中配置的宏又识别不了 遇到#ifdef包住的代码就会变暗色&#xff0c;想查看代码不是很方便。如下图&#xff1a; 一 解决&#xff1a; 在vscode中添加全局宏定义。 二 步骤&#xff1a…...

重装荣耀X14笔记本电脑踩坑记

这几天趁着有国补搞了台荣耀 X14笔记本电脑。到手后第一件事情对我来说当然是要重装成Windows 11 LTSC版。所以按以往的经验做了个USB启动安装盘&#xff0c;但发现上电后按F12能进入启动设备选择&#xff0c;可是USB分类下没有任何设备。重启按F2进入设置界面&#xff0c;关闭…...

Android `android.graphics.drawable` 包深度解析:架构与设计模式

Android android.graphics.drawable 包深度解析:架构与设计模式 目录 引言Drawable 概述Drawable 的架构 Drawable 类层次结构Drawable 的核心方法Drawable 的设计模式 装饰者模式工厂模式状态模式常用 Drawable 子类解析 BitmapDrawableShapeDrawableLayerDrawableStateList…...

Kotlin语言的软件工程

Kotlin语言的软件工程 引言 在现代软件开发中&#xff0c;选择合适的编程语言是项目成功的关键之一。随着移动互联网的迅猛发展&#xff0c;以及大数据和人工智能等新兴技术的崛起&#xff0c;Kotlin语言凭借其简洁、高效和安全等特性&#xff0c;迅速崛起为备受欢迎的编程语…...

面试经典 150 题——数组/字符串(一)

文章目录 1、合并两个有序数组1.1 题目链接1.2 题目描述1.3 解题代码1.4 解题思路 2、移除元素2.1 题目链接2.2 题目描述2.3 解题代码2.4 解题思路 3、删除有序数组中的重复项3.1 题目链接3.2 题目描述3.3 解题代码3.4 解题思路 4、删除有序数组中的重复项 II4.1 题目链接4.2 题…...

使用亚马逊针对 PyTorch 和 MinIO 的 S3 连接器实现可迭代式数据集

2023 年 11 月&#xff0c;Amazon 宣布推出适用于 PyTorch 的 S3 连接器。适用于 PyTorch 的 Amazon S3 连接器提供了专为 S3 对象存储构建的 PyTorch 数据集基元&#xff08;数据集和数据加载器&#xff09;的实现。它支持用于随机数据访问模式的地图样式数据集和用于流式处理…...

TestMAX/DFT Compiler:时序单元的类型、连接顺序和后DFT优化

相关阅读 TestMAX/DFT Compilerhttps://blog.csdn.net/weixin_45791458/category_12865937.html?spm1001.2014.3001.5482 时序单元的状态 未映射的时序单元(Unmapped Sequential Cell) 在Design Compiler读取了一个RTL设计后&#xff0c;Design Compiler内置的HDL Compiler工…...

CAN201 Introduction to Networking(计算机网络)Pt.3 网络层

文章目录 4.Network Layter&#xff08;网络层&#xff09;4.1 Overview4.2 Router&#xff08;路由器&#xff09;4.3 Internet Protocol4.4 IPv4 addressing4.5 NAT&#xff08;network address translation&#xff0c;网路地址转换&#xff09;4.6 IPv64.7 Generalized For…...

App Factory:简化和加速私人应用开发

App Factory是Codigger提供的一套先进的开发工具、库和API&#xff0c;旨在帮助开发人员在现有的软件基础上添加特定的功能或扩展。它为私人应用的创建、开发和发布提供了一整套先进的工具集、集成的相关资源库以及强大的API接口&#xff0c;使开发者能够在现有的Codigger架构之…...

PHP语言laravel框架中基于Redis的异步队列使用实践与原理

在 Laravel 中&#xff0c;基于 Redis 的异步队列是通过 Laravel 的队列系统与 Redis 服务结合来实现的。这种队列机制允许你将任务推送到队列中&#xff0c;并由后台工作进程异步处理这些任务。这样&#xff0c;你就可以将耗时的操作&#xff08;如发送邮件、处理视频、数据同…...

全面Kafka监控方案:从配置到指标

文章目录 1.1.监控配置1.2.监控工具1.3.性能指标系统相关指标GC相关指标JVM相关指标Topic相关指标Broker相关指标 1.4.性能指标说明1.5.重要指标说明 1.1.监控配置 开启JMX服务端口&#xff1a;kafka基本分为broker、producer、consumer三个子项&#xff0c;每一项的启动都需要…...

kipotix4靶机实战

信息收集 1.判断靶机ip 原理&#xff1a;开靶机之前nmap扫一次网段&#xff0c;再开靶机之后扫一次&#xff0c;查看多出来的ip就是靶机ip ip192.168.98.1742.判断端口服务&#xff0c;系统版本 a.确定端口 b.-p指定端口进一步收集 c.信息筛选 1.端口&#xff1a;22,80,139,…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

深入浅出Diffusion模型:从原理到实践的全方位教程

I. 引言&#xff1a;生成式AI的黎明 – Diffusion模型是什么&#xff1f; 近年来&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;领域取得了爆炸性的进展&#xff0c;模型能够根据简单的文本提示创作出逼真的图像、连贯的文本&#xff0c;乃至更多令人惊叹的…...