代码随想录二刷|回溯2

回溯

组合问题

方法

组合

题干

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

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

思路

(1)定义全局变量数组,作为存放组合的数组和存放最终答案的数组

(2)如果组合长度为k,加入答案,返回

(3)从起始的index出发,直到n,一次放入组合,递归调用下一个下标作为index,再弹出组合里面的index

1)起始的index表示考虑放入组合的元素开始的下标,index=2就是从下标为2的元素开始考虑是否加入组合

2)为什么递归调用的时候用i+1作为起始的index:已经选择了下标为i的元素,不走回头路,也不能重复选取

class Solution {
public:vector<vector<int>>res;vector<int>ans;void f(int n,int k,int index){if(ans.size()==k){res.push_back(ans);return;}// if(index+k>n){//     return;// }for(int i=index;i<=n;i++){ans.push_back(i);f(n,k,i+1);ans.pop_back();}}vector<vector<int>> combine(int n, int k) {f(n,k,1);return res;}
};

组合的优化

题干

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

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

思路

优化点:遍历的终点从n改成n-(k-ans.size())+1

因为如果剩下的元素不足够填满组合,就停下来

(n = 4,k = 3, 目前已经选取的元素数为0(ans.size为0),现在的index是1,n - (k - index) + 1 即 4 - ( 3 - 1) + 1 = 3,也就是说,组合的第一个匀速可以是1或2或3)

class Solution {
public:vector<vector<int>>res;vector<int>ans;void f(int n,int k,int index){if(ans.size()==k){res.push_back(ans);return;}for(int i=index;i<=n-(k-ans.size())+1;i++){ans.push_back(i);f(n,k,i+1);ans.pop_back();}}vector<vector<int>> combine(int n, int k) {f(n,k,1);return res;}
};

组合之和III

题干

找出所有相加之和为 nk 个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次

返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

思路

(1)结束条件:组合长度到k的时候,如果组合之和是n,那么存答案。无论组合之和是否为n,只要长度到k,都要返回

(2)遍历: 从起始值到9,依次加入组合,递归调用下一个值,将现在的元素从组合拿走

class Solution {
public:vector<vector  <int>>res;vector<int> ans;void f(int k,int n,int index){if(ans.size()==k){int s=0;for(int j=0;j<k;j++){s+=ans[j];}if(s==n)res.push_back(ans);return;}for(int i=index;i<=9;i++){ans.push_back(i);f(k,n,i+1);ans.pop_back();}}vector<vector<int>> combinationSum3(int k, int n) {f(k,n,1);return res;}
};

电话号码的字母

题干

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

思路

(1)首先找到数字和字母的映射

(2)递归参数:digits(数字构成的字符串),和character_index(表示现在要寻找并加入第几个数字对应的字母)

(3)递归终点:如果character_index等于数字个数,就返回

(4)先把当前考虑的数字从字符变成数字,再获取这个数字对应的字符串

(5)遍历这个字符串的所有字符,加入组合,递归输入当中的下一个数字,将字符移出组合

(6)额外加上对空输入的处理

class Solution {
public:string ans;vector<string> res;vector<string> match = {"",    "",    "abc",  "def", "ghi","jkl", "mno", "pqrs", "tuv", "wxyz"};void f(string digits, int character_index) {if (character_index == digits.size()) {res.push_back(ans);return;}int index = digits[character_index] - '0';string letter = match[index];for (int i = 0; i < letter.size(); i++) {ans.push_back(letter[i]);f(digits, character_index + 1);ans.pop_back();}}vector<string> letterCombinations(string digits) {if (digits.size() == 0)return res;f(digits, 0);return res;}
};

组合总和

题干

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

思路

(1)递归终点:

sum大于target返回

sum等于target存答案并返回

(2)从起始下标开始,迭代

1)加入组合,求sum

2)递归调用,注意起始下标改成i

表示在下标为i的元素加入组合之后,不走回头路,可以重复用下标为i的元素

3)弹出,sum减掉

class Solution {
public:vector<int> ans;vector<vector<int>> res;void f(vector<int>& candidates, int target, int sum, int start_i) {if (sum > target)return;if (sum == target) {res.push_back(ans);return;}for (int i = start_i; i < candidates.size(); i++) {ans.push_back(candidates[i]);sum += candidates[i];f(candidates, target, sum, i);sum -= candidates[i];ans.pop_back();}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {f(candidates, target, 0, 0);return res;}
};

组合之和II

题干

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次

**注意:**解集不能包含重复的组合。

思路
基本思路

(1)回溯框架

终止条件:和为target存答案,和大于target返回

单次递归:for循环,每次从start开始,加入组合+更新sum+更新used,递归调用(start为i+1),回溯(恢复组合,sum,used)

(2)去重:

1)重复的地方:candidates有重复的两个元素,考虑完第一个之后,再考虑第二个的话会产生一样的组合

2)解决:used标记元素是否在组合中使用

如果candidates[i] 和candidates[i - 1]相等,并且candidates[i - 1]没有在组合中使用(说明已经考虑过了candidates[i - 1]的所有组合),跳过

注意:先对candidates排队序,确保相同元素挨着

class Solution {
public:vector<int> ans;vector<vector<int>> res;void f(vector<int>& candidates, int target, int start, vector<int> used,int sum) {if (sum == target) {res.push_back(ans);return;}if (sum > target)return;for (int i = start; i < candidates.size(); i++) {if (i > 0 && candidates[i] == candidates[i - 1] &&used[i - 1] == false)continue;ans.push_back(candidates[i]);sum += candidates[i];used[i] = true;f(candidates, target, i + 1, used, sum);used[i] = false;sum -= candidates[i];ans.pop_back();}}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {vector<int> used(candidates.size(), false);sort(candidates.begin(), candidates.end());f(candidates, target, 0, used, 0);return res;}
};
剪枝优化

在for循环里,如果现有的和加上当前元素大于target,就停止循环(作为循环停止条件)

class Solution {
public:vector<int> ans;vector<vector<int>> res;void f(vector<int>& candidates, int target, int start, vector<int> used,int sum) {if (sum == target) {res.push_back(ans);return;}for (int i = start;i < candidates.size() && sum + candidates[i] <= target; i++) {if (i > 0 && candidates[i] == candidates[i - 1] &&used[i - 1] == false)continue;ans.push_back(candidates[i]);sum += candidates[i];used[i] = true;f(candidates, target, i + 1, used, sum);used[i] = false;sum -= candidates[i];ans.pop_back();}}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {vector<int> used(candidates.size(), false);sort(candidates.begin(), candidates.end());f(candidates, target, 0, used, 0);return res;}
};

回文子串

思路

for循环遍历的起点是start,每次寻找子字符串[start,i] ,如果是回文就加入组合,递归,不是就continue

class Solution {
public:vector<vector<string>> res;vector<string> ans;bool is_hui(string s, int l, int r) {for (int i = l; i <= r; i++) {if (s[i] != s[r - (i - l)])return false;}return true;}void f(string s, int start) {if (start >= s.size()) {res.push_back(ans);}for (int i = start; i < s.size(); i++) {if (is_hui(s, start, i)) {// string str(s.begin() + start, s.begin() + start + i + 1);string str = s.substr(start, i - start + 1);ans.push_back(str);f(s, i + 1);ans.pop_back();}}}vector<vector<string>> partition(string s) {f(s, 0);return res;}
};

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

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

相关文章

趣解单词,实现快速记忆

英文单词 love&#xff0c;是“爱”的意思&#xff1a; love v./n.爱&#xff1b;喜欢&#xff1b;热爱&#xff1b;爱情&#xff1b;心爱的人 那什么是爱呢&#xff1f;love&#xff0c;首字母为l&#xff0c;是一根绳子&#xff0c;ve-通f&#xff0c;love通life&#xff0…

PostgreSQL拼接字符串的几种方法简单示例例子解析

代码示例&#xff1a; 在PostgreSQL中&#xff0c;拼接字符串可以使用多种方法&#xff0c;以下是一些常用的方法和示例&#xff1a; 使用 || 操作符 这是最简单直接的字符串拼接方式。 SELECT Hello || || World AS ConcatenatedString;结果&#xff1a; ConcatenatedStrin…

4 [危机13小时追踪一场GitHub投毒事件]

事件概要 自北京时间 2024.12.4 晚间6点起&#xff0c; GitHub 上不断出现“幽灵仓库”&#xff0c;仓库中没有任何代码&#xff0c;只有诱导性的病毒文件。当天&#xff0c;他们成为了 GitHub 上 star 增速最快的仓库。超过 180 个虚假僵尸账户正在传播病毒&#xff0c;等待不…

Android学习19 -- 手搓App

1 前言 之前工作中&#xff0c;很多时候要搞一个简单的app去验证底层功能&#xff0c;Android studio又过于重型&#xff0c;之前用gradle&#xff0c;被版本匹配和下载外网包折腾的堪称噩梦。所以搞app都只有找应用的同事帮忙。一直想知道一些简单的app怎么能手搓一下&#x…

深度学习 Pytorch 神经网络的学习

本节将从梯度下降法向外拓展&#xff0c;介绍更常用的优化算法&#xff0c;实现神经网络的学习和迭代。在本节课结束将完整实现一个神经网络训练的全流程。 对于像神经网络这样的复杂模型&#xff0c;可能会有数百个 w w w的存在&#xff0c;同时如果我们使用的是像交叉熵这样…

使用1panel给neo4j容器安装apoc插件

文章目录 下载apoc插件安装apoc插件重启容器并验证 APOC插件是 Awesome Procedures of Cypher 是Neo4j图数据库的扩展过程和函数库。 下载apoc插件 apoc插件下载界面&#xff0c;选择与neo4j兼容的apoc版本apoc与neo4j版本对应表 安装apoc插件 需要挂载容器中/var/lib/ne…

e2studio开发RA2E1(5)----GPIO输入检测

e2studio开发RA2E1.5--GPIO输入检测 概述视频教学样品申请硬件准备参考程序源码下载新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置GPIO口配置按键口配置按键口&Led配置R_IOPORT_PortRead()函数原型R_IOPORT_PinRead()函数原型代码 概述 本篇文章主要介绍如何…

【漫话机器学习系列】070.汉明损失(Hamming Loss)

汉明损失&#xff08;Hamming Loss&#xff09; 汉明损失是多标签分类问题中的一种评价指标&#xff0c;用于衡量预测结果与实际标签之间的差异。它定义为预测错误的标签比例&#xff0c;即错误标签的个数占总标签数量的比值。 在多标签分类中&#xff0c;每个样本可以属于多…

洛谷网站: P3029 [USACO11NOV] Cow Lineup S 题解

题目传送门&#xff1a; P3029 [USACO11NOV] Cow Lineup S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 前言&#xff1a; 这道题的核心问题是在一条直线上分布着不同品种的牛&#xff0c;要找出一个连续区间&#xff0c;使得这个区间内包含所有不同品种的牛&#xff0c;…

docker pull Error response from daemon问题

里面填写 里面解决方案就是挂代理。 以虚拟机为例&#xff0c;将宿主机配置端口设置&#xff0c;https/http端口设为7899 配置虚拟机的http代理&#xff1a; vim /etc/systemd/system/docker.service.d/http-proxy.conf里面填写&#xff0c;wq保存 [Service] Environment…

【Rust自学】17.2. 使用trait对象来存储不同值的类型

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 17.2.1. 需求 这篇文章以一个例子来介绍如何在Rust中使用trait对象来存储不同值的类型。 在第 8 章中&#xff0c;我们提到Vector的一个…

Windows:AList+RaiDrive挂载阿里云盘至本地磁盘

零、前言 电脑存储的文件多了&#xff0c;出现存储空间不够用的情况。又没前买新的硬盘或者笔记本电脑没有额外的插槽提供给新的硬盘。遇到这种情况&#xff0c;我想到可以使用网盘&#xff0c;但单纯的网盘又要上传下载&#xff0c;极其麻烦。看到WPS云盘可以直接挂载本地&…

Redis缓存穿透、击穿、雪崩介绍以及解决方案

一、缓存穿透 1.1 什么是缓存穿透&#xff1f; 指的是&#xff0c;外部进来的请求&#xff0c;查询一个不存在的数据。Redis中没有&#xff0c;数据库中也没有&#xff0c;这时候如果外部恶意大量请求&#xff0c;所有请求会直接查询数据库&#xff0c;导致数据库崩溃 1.2 解决…

2025 持续防范 GitHub 投毒,通过 Sharp4SuoExplorer 分析 Visual Studio 隐藏文件

在2024年底的网络安全事件中&#xff0c;某提权工具被发现植入后门&#xff0c;攻击者利用 .suo 文件作为隐蔽的攻击方式。由于 .suo 文件是 Visual Studio 项目的隐藏配置文件&#xff0c;通常不为安全研究人员所关注&#xff0c;因此为攻击者提供了潜在的攻击渠道。 初步调查…

【Windows7和Windows10下从零搭建Qt+Leaflet开发环境】

Windows7和Windows10下从零搭建QtLeaflet开发环境 本文开始编写于2025年1月27日星期一&#xff08;农历&#xff1a;腊月二十八&#xff0c;苦逼的人&#xff0c;过年了还在忙工作&#xff09;。 第一章 概述 整个开发环境搭建需要的资源&#xff1a; 操作系统 Windows7_x6…

mysql 学习7 DCL语句,用来管理数据库用户,控制数据库的访问权限

DCL data control language 数据控制语言&#xff1a; 用来管理数据库用户&#xff0c;控制数据库的访问权限 有两个功能&#xff1a; 一&#xff0c;用户管理的SQL 语句&#xff0c;添加用户&#xff0c;删除用户&#xff0c;修改用户 查询用户 在mysql 中&#xff0c;用户…

8-登录流程

在AppStartInitFinish_CreateLoginUI.初始化后&#xff0c;执行Login界面的初始化 登录面板逻辑&#xff1a;UILoginComponentSystem,针对组件UILoginComponent创建的System 登录面板逻辑&#xff1a;UILoginComponent 逻辑层: LoginHelper中的clientSenderComponent.LoginA…

【远程控制】安装虚拟显示器

todesk远程发现没显示器的机器有问题 电脑如果不外接一个显示器那么会默认为1024 768 分辨率需要安装虚拟显示器参考 竟然是一个隐私屏幕的解决方案。 虚拟显示器 Parsec-vdd 项目地址 Parsec-vdd 最大的优点是&#xff1a;支持 4K 高刷、可添加多个虚拟屏、 H-Cursor&#…

安全实验作业

一 拓扑图 二 要求 1、R4为ISP&#xff0c;其上只能配置IP地址&#xff1b;R4与其他所有直连设备间均使用共有IP 2、R3-R5-R6-R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b; 4、所有设备均可访问R4的环回&#x…

响应式编程_02基本概念:背压机制 Backpressure

文章目录 Pre流流的处理模型拉模式推模式 流量控制产者生产数据的速率小于消费者的场景生产者生产数据的速率大于消费者消费数据无界队列有界丢弃队列有界阻塞队列 背压机制响应式流规范响应式流的核心接口PublisherSubscriberSubscription 响应式流的技术生态圈 小结 Pre 响应…