【蓝桥杯速成】| 9.回溯升级

news2025/4/21 15:45:05

题目一:组合综合

问题描述

39. 组合总和 - 力扣(LeetCode)

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

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

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

示例 1:

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

解题步骤

这一题是在组合总和③上有了进一步的改进和要求

我们依旧可以用回溯三部曲模板解决

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

这里我们需要从candidates数组中取值,所以这个数组应该一直陪伴我们,加入参数列表!

相当于我们之前从1~n中取值的n,都表示我们的取值范围

同理,我们需要一直参考target数值,所以它也是参数的一员

为了记录每个组合的总和,我们需要一个新变量用于存储,随之改变,所以加入新变量sum

最后仍然是我的开始索引,防止重复

void backtracking(vector<int>& candidates,int target,int sum,int startindex)

 2.确定终止条件

终止条件就是说我们找到答案会出现的情况,或者已知明确不可能出现答案就不要继续的情况

所以分开判断

if(sum>target){

        return;

}

if(sum==target){

        result.push_back(path);

        return;

}

3.单层搜索逻辑

使用for循环,遍历candidates数组中的每一个数字,

在每一层中我们需要往path中加入该数字

同时计算sum值

然后递归的使用backtracking函数,获得每一种可能情况

再进行回溯操作,sum值减去加入的数字值,数字也从path中pop_back

for(int i=startindex;i<candidates.size();i++){

        sum+=candidates[i];

        path.push_back(candidates[i]);

        backtracking(candidates,target,sum,startindex);//由于可以重复使用数字,所以此处startindex不需要+1

        sum-=candidates[i];

        path.pop_back();

}

最后只需要整合一下这个回溯函数,在主函数中正确传参调用即可!

完整代码如下! 

code

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

题目二:电话号码的字母组合

问题描述

17. 电话号码的字母组合 - 力扣(LeetCode)

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

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

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

解题步骤

想必缩写对应数字这事大家肯定很熟悉了

(在背后说人家坏话或者讲机密时就用数字代号的事没少干ψ(`∇´)ψ

那么这一题相较于之前的组合题区别就在于,它的选值对象不再是同一个范围内的数字了

而是存在数字对应字符串,在字符串中选取对应值,

并且这一题的组合长度也是固定的,给定dights有几位,我们的组合长度就是几位

简单分析就是这样,那当务之急就是解决数字对应字符串

这样才可以确定之后的取值范围

关于映射关系,我们可以选用数组和map

这里选择二维数组

const string lettermap[10]{

        "","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"

    };

 0号和1号位为空,虽然看似一维数组,但由于string可以按照数组使用,所以是二维滴!

同样,我们需要一个存储过程量和一个存储最后结果集的变量,

根据题目所求的数据类型,定义为👇

string s;//过程量,存储每一种可能

vector<string> result;//结果集,存放所有正确结果

ok,准备完毕,开始走回溯三部曲

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

这里我们不能一味的拿来之前的参数列表使用,一定要明确参数的意义

当然返回值依然是void

要把数字转化为对应字母,那我们就需要该数字,和取到哪一位数字的一个标识

可以这么想,我们的函数需要递归调用的,每次都需要看取哪一位元素,

所以digits用来看,index用来指并且是要动态改变的

void backtracking(const string& digits,int index) 

 2.终止条件

既然我们已经派出index指向我们所挑选的数字

那么只要index的数值等于digits的大小,那就意味着指到最后一位了,完成我们的任务了!

所以满足终止条件,我们需要加入这个s到结果集中并返回

if(index==digits.size()){

        result.push_back(s);

        return;

}

 3.单层遍历逻辑

我们需要遍历的是当前数字所对应的字符串(或者说字符数组)

所以在执行遍历之前,我们应该取出这个字符数组

取出字符数组又分为两步

1).确认当前数字

2).找数字对应字符数组

int digit=digits[index]-'0';//digits为字符串类型,取出类型需要通过-'0'转为int型

string letters=lettermap[digit];//在我们的对应二维数组中找到对应string

 ok万事大吉,开始进入单层遍历逻辑

为方便理解我们用digits = "23"来举例,最开始肯定是拿到2对应的字符串“abc”嘛

那就遍历这个字符串for(int i=0;i<letters.size();i++)

在这个循环里,把单个字符串加入到s中,第一个加入的是"a"

然后递归调用backtracking函数,我们就可以拿到3对应的字符串“def”

然后再遍历“def”,分别与a进行组合,得到三个组合,a这个结点就组合完毕

最外层就可以再指向下一个b,再与def进行同样的组合

过程类似下图,只举例了第一个a的情况

 那么我们的单层遍历代码如下:

for(int i=0;i<letters.size();i++){

        s.push_back(letters[i]);

        backtracking(digits,index+1);

        s.pop_back();

}

整合所有代码, 在主函数中调用即可

这里呢我们可以做一个剪枝操作,

如果给我们的数字序列为空,那么直接返回result(初始为空)即可

if(digits.size()==0){

        return result;

}

code

class Solution {
public:
    string s;
    vector<string> result;
    const string lettermap[10]{
        "","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"
    };

    void backtracking(const string& digits,int index){
        if(index==digits.size()){
            result.push_back(s);
            return;
        }
        int dight=digits[index]-'0';
        string letters=lettermap[dight];
        for(int i=0;i<letters.size();i++){
            s.push_back(letters[i]);
            backtracking(digits,index+1);
            s.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        if(digits.size()==0){
            return result;
        }
        backtracking(digits,0);
        return result;
    }
};

补充:

const 是 constant 的缩写,本意是不变的,不易改变的意思。在 C++ 中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。

C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助。


题目三:组合总和②

问题描述

40. 组合总和 II - 力扣(LeetCode)

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

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

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

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

解题步骤

不知道有没有和我一样的小蠢蛋,看到这一题没仔细审题还以为是之前做过没有提交

嘎嘎写完代码运行完才发现不对劲

这一题的特殊之处在于它所给的candidates是可能重复的,但最后要求解集中不能包含重复的

那么按照之前的逻辑,我们只能满足它在各不相同的情况下不重复,

但不能解决同一个取值空间中有相同元素的重复可能

所以这里我们要加入一个新的操作——去重

其它代码都大致相同就不多解释,重点来理一下去重的逻辑

我们需要在每一层去确认当前元素之前是否被使用过,

那么为了方便对比前后,可以先将整个candidates数组进行排序,

那相同值肯定就出现在旁边,不需要考虑是多久之前出现

sort(candidates.begin(), candidates.end());

同时需要留下记录,所以需要一个新的数组来存储这些记录

vector<bool> used(candidates.size(), false);//初始化为false全部没用过

那么这个used数组应该要伴随这组结果一直递归才能查看情况

所以把他加入参数列表

    void backtracking(vector<int>& candidates,int target,int sum,int index,vector<bool>& used){

那么在单层遍历中需要同时改变这个结点的使用状态

            sum+=candidates[i];

            path.push_back(candidates[i]);

            used[i]=true;

            backtracking(candidates,target,sum,i+1,used);

            used[i]=false;

            sum-=candidates[i];

            path.pop_back();

简单的已经铺垫完了,接下来捋一下去重方法

重复那就是candidates[i] == candidates[i - 1],但是只加这一个条件会使我们失去确实用到两个相同元素的结果,而不是仅去掉重复的结果(细品这个差别)

所以还需要加上used[i - 1] == false代表对于同一树层candidates[i - 1]使用过(因为回溯所以false)

在满足这两个条件下我们就需要continue跳过这个组合结果

if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {

                continue;

            }

完整代码如下! 

code

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

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

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

相关文章

【uni-app】引用公共组件

目录 一、建立公共组件 1.1新建vue文件 1.2编写公共文件代码 1.3使用 注意事项 一、建立公共组件 1.1新建vue文件 在公共组件文件目录下新建所需要的功能文件 1.2编写公共文件代码 按需求写对应功能的代码 1.3使用 在需要使用的文件下引用公共组件 注意事项 想要使用s…

API-Arrays

Arrays 操作数组的工具类 1.tostring import java.util.Arrays;public class demo1 {public static void main(String[] args) {Integer[] arr {2, 3, 1, 5, 6, 7, 8, 4, 9};System.out.println(Arrays.toString(arr));//[2, 3, 1, 5, 6, 7, 8, 4, 9]} } 2.binarySearch 二…

尝试在软考62天前开始成为软件设计师-信息系统安全

安全属性 保密性:最小授权原则(能干活的最小权限)、防暴露(隐藏)、信息加密、物理保密完整性(防篡改):安全协议、校验码、密码校验、数字签名、公证 可用性:综合保障( IP过滤、业务流控制、路由选择控制、审计跟踪)不可抵赖性:数字签名 对称加密 DES :替换移位 3重DESAESR…

dsPIC33CK64MC105 Curiosity Nano|为高性能数字电源与电机控制而生

「dsPIC33CK64MC105 Curiosity Nano」面向高性能数字电源与电机控制而生 dsPIC33CK64MC105 Curiosity Nano 该评估套件是一个经济高效的硬件平台&#xff0c;用于评估dsPIC33CK系列高性能数字信号控制器&#xff08;DSC&#xff09;。该板采用 100 MHz dsPIC33CK64MC105 DSC&am…

《面向车险理赔的事故信息提取》开题报告

个人主页&#xff1a;大数据蟒行探索者 目录 一、选题的依据及意义 二、国内外研究概况及发展趋势 &#xff08;1&#xff09;车牌识别技术 &#xff08;2&#xff09;证件信息提取技术 &#xff08;3&#xff09;交通事故认定书文本提取 三、研究内容及实验方案 1.研究…

【AI神经网络】深度神经网络(DNN)技术解析:从原理到实践

引言 深度神经网络&#xff08;Deep Neural Network, DNN&#xff09;作为人工智能领域的核心技术&#xff0c;近年来在计算机视觉、自然语言处理、医疗诊断等领域取得了突破性进展。与传统机器学习模型相比&#xff0c;DNN通过多层非线性变换自动提取数据特征&#xff0c;解决…

EasyRTC轻量级Webrtc音视频通话SDK,助力带屏IPC在嵌入式设备中的应用

一、市场背景 随着人们生活水平的提高&#xff0c;对于家居安全和远程监控的需求日益增长&#xff0c;带屏IPCam不仅满足了用户实时查看监控画面的需求&#xff0c;还提供了诸如双向语音通话、智能报警等丰富的功能&#xff0c;极大地提升了用户体验。 此外&#xff0c;技术的…

预测数值型数据:回归

1.1 用线性回归找到最佳拟合直线 线性回归&#xff1a;优点&#xff1a;结果易于理解&#xff0c;计算上不复杂 缺点&#xff1a;对非线性的数据拟合不好 适用数据类型&#xff1a;数值型和标称型数据 回归的目的就是预测数值型的目标值。 回归的一般方法&#xff1a; &#…

【操作系统安全】任务3:Linux 网络安全实战命令手册

目录 一、基础网络信息获取 1. 网络接口配置 2. 路由表管理 3. 服务端口监控 二、网络监控与分析 1. 实时流量监控 2. 数据包捕获 3. 网络协议分析 三、渗透测试工具集 1. 端口扫描 2. 漏洞利用 3. 密码破解 四、日志审计与分析 1. 系统日志处理 2. 入侵检测 3…

5.4 位运算专题:LeetCode 137. 只出现一次的数字 II

1. 题目链接 LeetCode 137. 只出现一次的数字 II 2. 题目描述 给定一个整数数组 nums&#xff0c;其中每个元素均出现 三次&#xff0c;除了一个元素只出现 一次。请找出这个只出现一次的元素。 要求&#xff1a; 时间复杂度为 O(n)&#xff0c;空间复杂度为 O(1)。 示例&a…

3. 轴指令(omron 机器自动化控制器)——>MC_SetPosition

机器自动化控制器——第三章 轴指令 11 MC_SetPosition变量▶输入变量▶输出变量▶输入输出变量 功能说明▶时序图▶重启动运动指令▶多重启运动指令▶异常 MC_SetPosition 将轴的指令当前位置和反馈当前位置变更为任意值。 指令名称FB/FUN图形表现ST表现MC_SetPosition当前位…

Python+Requests+Pytest+YAML+Allure接口自动化框架

GitHub源码地址&#xff08;详细注释&#xff09;&#xff1a;源码 调试项目python自主搭建&#xff1a;附项目源码 一、项目介绍 本项目是基于 PythonRequestsPytestYAMLAllure 搭建的 接口自动化测试框架&#xff0c;用于对 REST API 进行测试。 框架的主要特点包括&#…

用 Python 也能做微服务?

一、Python 和微服务&#xff0c;是敌是友&#xff1f; Python 因其极强的开发效率与生态&#xff0c;一直是数据处理、AI、Web 开发的主力选手。但在“微服务”这个领域&#xff0c;它一直处于边缘地带&#xff1a; 服务注册 / 发现&#xff1f;&#x1f937;‍♂️ 没有统一…

Maya基本操作

基本操作 按住ALT键&#xff0c;左键旋转视角&#xff0c;中键平移视角&#xff0c;右键放大缩小视角。 按空格键切换4格视图。 导入FBX格式文件后&#xff0c;无贴图显示。 按6键开启。着色纹理显示 坐标轴相关 修改菜单-左键最上面的虚线。固定修改选项窗口。 选中物体…

SQL Server Management Studio(SSMS)安装教程

目录 一、SSMS的下载 二、SSMS 的安装 三、连接服务器 四、卸载 SSMS 一、SSMS的下载 1.进入 SQL Server Management Studio 官方下载页面&#xff1a;SQL Server Management Studio点击进入下载页面 2.点击链接开始下载&#xff0c;浏览器右上角会显示下载进度&#xff1b;…

若依前端框架增删改查

1.下拉列表根据数据库加载 这个是用来查询框 绑定了 change 事件来处理站点选择变化后的查询逻辑。 <el-form-item label"站点选择" prop"stationId" v-has-permi"[ch:m:y]"><el-select v-model"queryParams.stationId" pl…

LiteratureReading:[2023] GPT-4: Technical Report

文章目录 一、文献简明&#xff08;zero&#xff09;二、快速预览&#xff08;first&#xff09;1、标题分析2、作者介绍3、引用数4、摘要分析&#xff08;1&#xff09;翻译&#xff08;2&#xff09;分析 5、总结分析&#xff08;1&#xff09;翻译&#xff08;2&#xff09;…

Walrus 经济模型 101

本文作者&#xff1a;Steve_4P&#xff0c;文章仅代表作者观点。 要点总结 2025 年 3 月 20 日&#xff0c;Walrus 基金会宣布成功融资 约 1.4 亿美元&#xff0c;投资方包括 Standard Crypto、a16z 等机构。Walrus 当前估值约 20 亿美元&#xff0c;其中 7% 代币供应量分配给…

SpringCould微服务架构之Docker(1)

项目中微服务比较多的时候&#xff0c;一个一个手动的部署太麻烦了&#xff0c;所以就需要用到Docker。 项目部署中的问题&#xff1a; Docker是一种快速交付应用、运行应用的技术。

mac丝滑安装Windows操作系统【丝滑简单免费】

mac丝滑安装Windows操作系统【丝滑&简单&免费】 记录mac丝滑安装windows系统1、安装免费版 VMware fusion 132、安装Windows镜像文件3、跳过联网安装&#xff08;完成1后将2拖入1 点点点 即可来到3的环节&#xff09;4、 安装vmware 工具【非常重要&#xff0c;涉及联网…