代码随想录算法训练营DAY25|C++回溯算法Part.2|216. 组合总和III、17.电话号码的字母组合

news2025/5/25 14:49:22

文章目录

  • 216. 组合总和III
    • 题意理解
    • 树形结构
    • 伪代码实现
    • 剪枝操作
    • CPP代码实现
  • 17.电话号码的字母组合
    • 解题思路
    • 树形结构
    • 伪代码实现
    • 隐藏回溯
    • CPP代码

216. 组合总和III

力扣题目链接

文章讲解:216. 组合总和III

视频讲解:和组合问题有啥区别?回溯算法如何剪枝?| LeetCode:216.组合总和III

状态:根据题目可知,k是决定树形结构的深度,那么要求组合为n的这个限制条件,我们如何写代码呢?

题意理解

题目其实就是给定一个[1, 9]的集合,求组合,要求组合和为n,个数为k

本质上就是在组合问题的基础上加了一个和的限制。

树形结构

树的宽度由我们的集合长度决定 [ 1 , 9 ] [1, 9] [1,9],树的深度由k来决定。

伪代码实现

定义全局变量path和result

  • 确定参数和返回值:
    • 参数——targetSum也就是我们的限定条件,组合的和为n
    • 组合大小k
    • 当前路径之和sum。
    • 最后我们会拿sumtarget Sum比较。还有一个重要参数startIndex.
void backtracking(targetSum, k, Sum, startIndex)
  • ⭐️递归的终止条件:本题的递归终止条件我的错误写法需要注意
//本段代码会导致错误:runtime error: signed integer overflow
if (path.size() == k && targetSum == sum){
	result.push_back(path);
	return
}
if (path.size() == k){
  if (targetSum == Sum) result.push_back(path);
  return}
  • 单层递归逻辑:求和和路径都必须进行回溯。
for (int i = startIndex; i <= 9; i++){
  	sum += i;
	path.push_back(i);
  	backtracking(targetSum, k, Sum, i + 1);
  	sum -= i;
  	path.pop_back();
}

剪枝操作

这里的剪枝操作就是:已选元素总和已经大于n了,那么往后遍历是没有意义的,直接剪掉

剪枝操作可以放到递归函数开始的地方。

if (sum > targeetSum){
  return; 
}

这里写return其实也是回溯的一种体现,因为从目前的i开始,一直往后所有的i都不需要了

for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i ++){
    sum += i; // 处理
    path.push_back(i); // 处理
    if (sum > targetSum) { // 剪枝操作
        sum -= i; // 剪枝之前先把回溯做了
        path.pop_back(); // 剪枝之前先把回溯做了
        return;
    }
    backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
    sum -= i; // 回溯
    path.pop_back(); // 回溯
}

CPP代码实现

class Solution {
private:
    vector<vector<int>> result; // 存放结果集
    vector<int> path; // 符合条件的结果
    void backtracking(int targetSum, int k, int sum, int startIndex) {
        if (sum > targetSum) { // 剪枝操作
            return; 
        }
        if (path.size() == k) {
            if (sum == targetSum) result.push_back(path);
            return; // 如果path.size() == k 但sum != targetSum 直接返回
        }
        for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) { // 剪枝
            sum += i; // 处理
            path.push_back(i); // 处理
            backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
            sum -= i; // 回溯
            path.pop_back(); // 回溯
        }
    }

public:
    vector<vector<int>> combinationSum3(int k, int n) {
        result.clear(); // 可以不加
        path.clear();   // 可以不加
        backtracking(n, k, 0, 1);
        return result;
    }
};

17.电话号码的字母组合

力扣题目链接

文章讲解:17.电话号码的字母组合

视频讲解:还得用回溯算法!| LeetCode:17.电话号码的字母组合

状态:这个映射好难,甚至树形结构都画不出来有点难受。主要是问题:

  1. 待选元素的集合怪怪的,感觉是一个二维数组,也就是说我们要用两层循环控制回溯了吗?
  2. 树形结构怎么画?

解题思路

解决三个问题:

  1. 数字和字母的映射
  2. 两个字母就两个for循环,三个字符三个for循环,以此类推,然后发现代码根本写不出来
  3. 处理输入的异常情况

数字到字母的映射可以用map,也可以用二维数组来做映射。

本题中使用二维数组来做映射,这里也回答了状态1中提出的问题

树形结构

这里的树形结构应该是什么样的呢?真的很难画,这里给出了状态2中提出问题的答案

树的深度是由我们输入的数字个数来定,树的宽度就是数字所对应的字母的长度来控制

伪代码实现

定义全集变量string来收获单个结果;然后用result数组来收集全部结果

string S;
vector<string> result;
  • 递归的返回值和参数:传入数字组合digits(要注意digits是字符串类型); index来表示递归中它告诉我我传入的字符串遍历到哪一个数字了。

从树形结构可以看出,我们需要知道目前递归遍历到了哪一个数字

void backtracking(string digits, index){
  
}
  • 终止条件:由于index是来告诉我们遍历的当前数字,所以等index遍历完最后一个数字后,递归结束。所以终止代码应该是index == digits.size()而不是index == digits.size()-1
if (index == digits.size()){
  result.push_back(s);
  return;
}
  • 单层遍历/递归逻辑:

    • const string letterMap[10] = {
          "", // 0
          "", // 1
          "abc", // 2
          "def", // 3
          "ghi", // 4
          "jkl", // 5
          "mno", // 6
          "pqrs", // 7
          "tuv", // 8
          "wxyz", // 9
      };
      
int digit = digits[index] - '0'; //这样字母就变成了一个数字
string letter = letterMap[digit];
for (int i = 0; i < letter.size; i++){
  s.push_back(letter[i]);
  backtracking(digits, index + 1);
  s.pop_back;
}

隐藏回溯

将回溯过程隐藏在参数中:

backtracking(digits, index+1, s+letter[i]);

CPP代码

总体C++代码如下:

// 版本一
class Solution {
private:
    const string letterMap[10] = {
        "", // 0
        "", // 1
        "abc", // 2
        "def", // 3
        "ghi", // 4
        "jkl", // 5
        "mno", // 6
        "pqrs", // 7
        "tuv", // 8
        "wxyz", // 9
    };
public:
    vector<string> result;
    string s;
    void backtracking(const string& digits, int index) {
        if (index == digits.size()) {
            result.push_back(s);
            return;
        }
        int digit = digits[index] - '0';        // 将index指向的数字转为int
        string letters = letterMap[digit];      // 取数字对应的字符集
        for (int i = 0; i < letters.size(); i++) {
            s.push_back(letters[i]);            // 处理
            backtracking(digits, index + 1);  // 递归,注意index+1,一下层要处理下一个数字了
            s.pop_back();                       // 回溯
          //三段代码可以写成backtracking(digits, index+1, s+letter[i])
        }
    }
    vector<string> letterCombinations(string digits) {
        s.clear();
        result.clear();
        if (digits.size() == 0) {
            return result;
        }
        backtracking(digits, 0);
        return result;
    }
};

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

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

相关文章

Oracle获取对象的DDL创建语句

1.命令行方式&#xff08;如&#xff1a;sqlplus&#xff09; ## 用户 select dbms_metadata.get_ddl(USER,TEST) from dual;## 表 select dbms_metadata.get_ddl(TABLE,TEST,T1) from dual;## 表空间 select dbms_metadata.get_ddl(TABLESPACE,TBS_NAME) from dual;## 索引 s…

【MySQL】:深入解析多表查询(下)

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. 自连接1.1 自连接查询1.2 联合查询 二. 子查询2.1 概述2.2 分类2.3 标量子查…

Linux数据库自动备份 - 定时任务发到百度云盘、坚果云、邮箱附件

前言 1. 坚果云的webdav云盘最好&#xff01; &#xff08;免费账号每月1G上传流量&#xff09; 2. 不建议数据库备份文件发送到SMTP邮箱&#xff0c;因为对方服务器非常容易当做垃圾邮件处理&#xff0c;而且发信的SMTP账号会被封禁&#xff08;实测163发到QQ邮箱被封&…

区块链媒体推广的8个成功案例解析-华媒舍

区块链领域作为一个新兴行业&#xff0c;媒体推广对于项目的成功发展起着至关重要的作用。本文将从八个成功案例中来分析区块链媒体推广的重要性和成功策略。 1. 媒体报道对于区块链项目的重要影响 媒体报道是提升区块链项目知名度和用户认可度的重要手段。对于区块链项目来说…

蓝桥杯备赛:考前注意事项

考前注意事项 1、DevCpp添加c11支持 点击 工具 - 编译选项 中添加&#xff1a; -stdc112、万能头文件 #include <bits/stdc.h>万能头文件的缺陷&#xff1a;y1 变量 在<cmath>中用过了y1变量。 #include <bits/stdc.h> using namespace std;// 错误示例 …

大厂Java笔试题之百钱买百鸡问题

题目&#xff1a;公元五世纪&#xff0c;我国古代数学家张丘建在《算经》一书中提出了"百鸡问题"&#xff1a;鸡翁一值钱五&#xff0c;鸡母一值钱三&#xff0c;鸡雏三值钱一。 百钱买百鸡&#xff0c;问鸡翁、鸡母、鸡雏各几何&#xff1f; 现要求你打印出所有花一…

“企业付款到零钱”和“商家转账到零钱”区别是什么

商家转账到零钱是什么&#xff1f; 商家转账到零钱是微信商户号里的一个功能&#xff0c;很早以前叫企业付款到零钱。 从2022年5月18日&#xff0c;原“企业付款到零钱”升级为“商家转账到零钱”&#xff0c;已开通商户的功能使用暂不受影响&#xff0c;新开通商户可前往「产…

网络篇01 | 入门篇

网络篇01 | 入门篇 01 各层协议目录[网络篇02 | 应用层 kcp&#xff08;王者荣耀&#xff09;](https://blog.csdn.net/qiushily2030/article/details/135835946)[网络篇03 | 应用层 quic](https://blog.csdn.net/qiushily2030/article/details/136192481)网络篇04 | 应用层 mq…

每日一题---OJ题: 环形链表

片头 嗨! 小伙伴们,大家好! 今天我们来讲讲这道OJ题----环形链表,准备好了吗? 我们开始咯! 题目似乎有点抽象,我们举几个例子哈 上图中,总共有4个结点,分别为 3, 2, 0, -4, 链表中有一个环,尾结点连接到第二个结点。 上图中,总共有2个结点,分别为 1, 2, 链表中有一个环, 尾结…

基于Springboot的汉服推广网站

基于SpringbootVue的汉服推广网站设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录页 首页 图文动态区 视频动态区 近期活动 汉服交流 汉服知识 后台登录页 后台首页…

牛客研究生复试刷题(1)

KY30进制转换 1.最开始没有考虑到大数问题,可以说是没考虑完全,输入类型使用的是int64_t,只ac了一半测试用例。所以在数很大找不到合适的数据类型存储时,要考虑使用string来存放。 2.使用string存放数字的时候就要考虑:字符和数字之间的转换。字符转换成数字:str[i]-0,…

第1章、react基础知识;

一、react学习前期准备&#xff1b; 1、基本概念&#xff1b; 前期的知识准备&#xff1a; 1.javascript、html、css&#xff1b; 2.构建工具&#xff1a;Webpack&#xff1a;https://yunp.top/init/p/v/1 3.安装node&#xff1a;npm&#xff1a;https://yunp.top/init/p/v/1 …

Java基础-知识点03(面试|学习)

Java基础-知识点03 String类String类的作用及特性String不可以改变的原因及好处String、StringBuilder、StringBuffer的区别String中的replace和replaceAll的区别字符串拼接使用还是使用StringbuilderString中的equal()与Object方法中equals()区别String a new String("a…

论文笔记:A Simple and Effective Pruning Approach for Large Language Models

iclr 2024 reviewer 评分 5668 1 intro 大模型网络剪枝的paper 在努力保持性能的同时&#xff0c;舍弃网络权重的一个子集现有方法 要么需要重新训练 这对于十亿级别的LLMs来说往往不现实要么需要解决依赖于二阶信息的权重重建问题 这同样可能带来高昂的计算成本——>引入…

ELK、ELKF企业级日志分析系统介绍

前言 随着企业级应用系统日益复杂&#xff0c;随之产生的海量日志数据。传统的日志管理和分析手段&#xff0c;难以做到高效检索、实时监控以及深度挖掘潜在价值。在此背景下&#xff0c;ELK日志分析系统应运而生。"Elastic" 是指 Elastic 公司所提供的一系列与搜索…

IDEA Warnings:SQL dialect is not configured.

springboot项目XxxMapper.xml文件打开后显示warnings&#xff1a;SQL dialect is not configured......&#xff08;翻译&#xff1a;未配置SQL语言。&#xff09; 大概意思是没有在IDEA中配置当前sql是MySQl、Oracle还是MariaDB等语言。 配置一下就好&#xff1a; 完了&#…

C语言: 字符串函数(下)

片头 在上一篇中,我们介绍了字符串函数。在这一篇章中&#xff0c;我们将继续学习字符串函数&#xff0c;准备好了吗&#xff1f;开始咯&#xff01; 1.strncpy函数 1.1 strncpy函数的用法 strncpy是C语言中的一个字符串处理函数&#xff0c;它用于将一个字符串的一部分内容…

基于SpringBoot实现的在线拍卖系统

系统开发环境 编程语言&#xff1a;Java数据库&#xff1a;MySQL容器&#xff1a;Tomcat工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统实现 管理员功能模块 首页 修改密码 用户管理 商品类型管理 拍卖商品 竞拍公告 轮播图 历史竞拍管理 竞拍订单管理 留言板管理 用户…

selenium添加代理(有账号密码)

以下为各种尝试的记录&#xff0c;正确实现可直接参考最后一条&#xff01; 1&#xff0c;导入Proxy库来添加capabilities属性&#xff1a;可以访问网站&#xff0c;但ip还是本机ip from selenium import webdriver from selenium.webdriver.chrome.options import Options f…

【Java探索之旅】方法重载 递归

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、方法重载1.1 为什么要有方法重载1.2 方法重载的概念与使用1.3 方法签名 二、递归2…