代码学习记录21--回溯算法第二天

news2024/12/23 17:37:59

随想录日记part21

t i m e : time: time 2024.03.16



主要内容:今天主要是结合类型的题目加深对回溯算法的理解:1:组合总和;2:电话号码的字母组合

  • 216.组合总和III
  • 17.电话号码的字母组合


Topic1组合总和

题目:

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

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

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

输入: k = 3 , n = 9 k = 3, n = 9 k=3,n=9
输出: [ [ 1 , 2 , 6 ] , [ 1 , 3 , 5 ] , [ 2 , 3 , 4 ] ] [[1,2,6], [1,3,5], [2,3,4]] [[1,2,6],[1,3,5],[2,3,4]]
解释:
1 + 2 + 6 = 9 1 + 2 + 6 = 9 1+2+6=9
1 + 3 + 5 = 9 1 + 3 + 5 = 9 1+3+5=9
2 + 3 + 4 = 9 2 + 3 + 4 = 9 2+3+4=9
没有其他符合的组合了。

思路: 按照回溯模板我们进行回溯三部曲:
递归三部曲:

1.回溯函数模板返回值以及参数
在这里要定义两个全局变量, p a t h path path用来存放符合条件单一结果, r e s u l t result result用来存放符合条件结果的集合。回溯函数里一定有两个参数,既然是集合 [ 1 , 9 ] [1,9] [1,9] 里面取 k k k 个数和为 n n n,所以需要 n n n k k k 是两个 i n t int int 的参数。还需要一个参数为 i n t int int 型变量 s t a r t I n d e x startIndex startIndex,这个参数用来记录本层递归的中,集合从哪里开始遍历(集合就是 [ 1 , . . . , n ] [1,...,n] [1,...,n] )。
所以整体代码如下:

List<List<Integer>> result=new ArrayList<>();
LinkedList<Integer> path=new LinkedList<>();
private void backtracking(int n,int k, int statindex){}

2.回溯函数终止条件
回溯出口,如果 p a t h path path 里面的数量等于 K K K,说明其到达叶子节点,若 p a t h path path 中所有元素之和为 n n n,则将其加入到 r e s u l t result result,否则直接返回 r e t u r n return return
代码如下:

if (k == path.size()) {// 回溯出口,如果Path里面的数量等于K,说明其到达叶子节点
            int sum = 0;
            for (int i = 0; i < k; i++) {
                sum += path.get(i);
            }
            if (sum == targetSum)
                result.add(new ArrayList<>(path));
            return;// 如果path.size() == k 但sum != targetSum 直接返回
        }

3.回溯搜索的遍历过程
f o r for for 循环每次从 s t a r t I n d e x startIndex startIndex 开始遍历,然后用 p a t h path path 保存取到的节点i搜索的过程如下图:
在这里插入图片描述

实现代码如下:

for (int i = startindex; i <= 9; i++) {
            path.add(i);
            backtracking(targetSum, k, i + 1);
            path.removeLast();
        }

完整的代码如下:

class Solution {
    List<List<Integer>> result = new ArrayList<>();// 存放结果集合
    LinkedList<Integer> path = new LinkedList<>();// 存放一个满足条件的路径
    public List<List<Integer>> combinationSum3(int k, int n) {
        result.clear();
        path.clear();
        backtracking(n, k, 1);
        return result;
    }
    // targetSum:目标和,也就是题目中的n。
    // k:题目中要求k个数的集合。
    // startIndex:下一层for循环搜索的起始位置。
    private void backtracking(int targetSum, int k, int startindex) {
        if (k == path.size()) {// 回溯出口,如果Path里面的数量等于K,说明其到达叶子节点
            int sum = 0;
            for (int i = 0; i < k; i++) {
                sum += path.get(i);
            }
            if (sum == targetSum)
                result.add(new ArrayList<>(path));
            return;
        }
        for (int i = startindex; i <= 9; i++) {
            path.add(i);
            // sum += i;
            backtracking(targetSum, k, i + 1);
            // sum -= i;
            path.removeLast();
        }
    }

}


Topic2电话号码的字母组合

题目:

给定一个仅包含数字 2 2 2- 9 9 9 的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 1 1 不对应任何字母。
在这里插入图片描述

输入: d i g i t s = " 23 " digits = "23" digits="23"
输出: [ " a d " , " a e " , " a f " , " b d " , " b e " , " b f " , " c d " , " c e " , " c f " ] ["ad","ae","af","bd","be","bf","cd","ce","cf"] ["ad","ae","af","bd","be","bf","cd","ce","cf"]

思路: 按照回溯模板我们进行回溯三部曲:
递归三部曲:

1.回溯函数模板返回值以及参数
在这里要定义两个全局变量, t e m p temp temp用来存放符合条件单一结果, l i s t list list用来存放符合条件结果的集合,与此同时我们需要建立一个数字到字符的映射,我们使用字符串数组 n u m S t r i n g numString numString 表示,还需要一个记录查到第几个第几个字符的索引 s t a r t i n d e x startindex startindex
所以整体代码如下:

// 设置全局列表存储最后的结果
List<String> list = new ArrayList<>();
// 每次迭代获取一个字符串,所以会设计大量的字符串拼接,所以这里选择更为高效的     
StringBuild StringBuilder temp = new StringBuilder();
void backtracking(String digits, String[] numString, int startindex)

2.回溯函数终止条件
回溯出口,如果索引值 s t a r t i n d e x startindex startindex 里面的数量等于 d i g i t s . l e n g t h ( ) digits.length() digits.length(),说明其到达叶子节点,则将 t e m p temp temp其加入到 l i s t list list,否则直接返回 r e t u r n return return
代码如下:

if (startindex == digits.length()) {// 查完最后一个字符,到达回溯出口
	list.add(temp.toString());
    return;
}

3.回溯搜索的遍历过程
f o r for for 循环每次从 s t a r t I n d e x startIndex startIndex 开始遍历,然后用 t e m p temp temp 保存取到的节点i搜索的过程如下图:
在这里插入图片描述

实现代码如下:

String str = numString[digits.charAt(startindex) - '0'];
        for (int i = 0; i < str.length(); i++) {
            temp.append(str.charAt(i));
            backtracking(digits, numString, startindex + 1);
            temp.deleteCharAt(temp.length() - 1);      
        }

完整的代码如下:

class Solution {
    List<String> list = new ArrayList<>();// 设置全局列表存储最后的结果
    // 每次迭代获取一个字符串,所以会设计大量的字符串拼接,所以这里选择更为高效的 StringBuild
    StringBuilder temp = new StringBuilder();
    public List<String> letterCombinations(String digits) {
        if (digits == null || digits.length() == 0)
            return list;
        // 初始对应所有的数字,为了直接对应2-9,新增了两个无效的字符串""
        String[] numString = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
        backtracking(digits, numString, 0);
        return list;
    }

    private void backtracking(String digits, String[] numString, int startindex) {
        if (startindex == digits.length()) {// 查完最后一个字符,到达回溯出口
            list.add(temp.toString());
            return;
        }
        // 得到digits[startindex]映射的字符串
        String str = numString[digits.charAt(startindex) - '0'];
        for (int i = 0; i < str.length(); i++) {
            temp.append(str.charAt(i));
            backtracking(digits, numString, startindex + 1);
            temp.deleteCharAt(temp.length() - 1);      
        }
    }
}

时间复杂度: O ( 3 m ∗ 4 n ) O(3^m * 4^n) O(3m4n),其中 m 是对应四个字母的数字个数,n 是对应三个字母的数字个数
空间复杂度: O ( 3 m ∗ 4 n ) O(3^m * 4^n) O(3m4n)

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

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

相关文章

快速了解微软推出的开发人员主页的应用

一、概述 开发人员主页是微软推出的一个新的 Windows 控制中心&#xff0c;提供以下功能&#xff1a;使用可自定义小组件监视仪表板中的项目&#xff0c;通过下载应用、包或存储库来设置开发环境&#xff0c;连接到开发人员帐户和工具&#xff08;如 GitHub&#xff09;&#x…

【C++进阶】深度解析AVL树及其简单模拟实现

AVL树的解析和模拟实现 一&#xff0c;什么是AVL树二&#xff0c;AVL树的特性三&#xff0c;模拟实现1. 基本框架2. 插入&#xff08;不带旋转&#xff09;2. AVL树的旋转3. AVL树的验证 四&#xff0c;总结 一&#xff0c;什么是AVL树 之前我们学习了二叉搜索树&#xff0c;但…

【每日力扣】40.组合总和II与701. 二叉搜索树中的插入操作

&#x1f525; 个人主页: 黑洞晓威 &#x1f600;你不必等到非常厉害&#xff0c;才敢开始&#xff0c;你需要开始&#xff0c;才会变的非常厉害。 40.组合总和II 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为…

【小白学机器学习8】统计里的自由度DF=degree of freedom, 以及关于df=n-k, df=n-k-1, df=n-1 等自由度公式

目录 1 自由度 /degree of freedom / df 1.1 物理学的自由度 1.2 数学里的自由度 1.2.1 数学里的自由度 1.2.2 用线性代数来理解自由度&#xff08;需要补充&#xff09; 1.2.3 统计里的自由度 1.3 统计学里自由度的定义 2 不同对象的自由度 2.1 纯公式的自由度&#…

报Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String错误

在springboot中使用Mybatis出现Invalid value type for attribute factoryBeanObjectType: java.lang.String 1、没有使用mybatis 检查pom文件里面的mybatis 可能是缺少这个依赖&#xff0c;或者版本过低 重新导入依赖 <dependency><groupId>org.mybatis.spri…

华为数通方向HCIP-DataCom H12-821题库(多选题:141-160)

第141题 以下关于802.1X认证的触发机制,描述正确的有? A、802.1X认证不能由认证设备(如802.1交换机)发起 B、802.1X客户端可以组播或广播方式触发认证 C、认证设备可以以组播或单播方式触发认证 D、802.1X认证只能由客户端主动发起 【参考答案】BC 【答案解析】 第142题 以…

集合系列(二) -List接口详解

一、List简介 List 的数据结构就是一个序列&#xff0c;存储内容时直接在内存中开辟一块连续的空间&#xff0c;然后将空间地址与索引对应。 以下是List集合简易架构图 由图中的继承关系&#xff0c;可以知道&#xff0c;ArrayList、LinkedList、Vector、Stack都是List的四个…

B3620 x 进制转 10 进制(详解)

题目 思路 八进制数567怎么转化为十进制数。首先八进制就是逢八进一&#xff0c;也就是说这里面最大的数也就7&#xff0c;没有≥8的数。下面我们就讲一下567怎么转化为十进制&#xff1a;首先7是个位&#xff0c;可以直接写成十进制的7&#xff0c;6是十位&#xff0c;它是通…

springboot基于java的畅销图书推荐系统

摘 要 二十一世纪我们的社会进入了信息时代&#xff0c;信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针对这一…

AI_寻路系统_修改寻路网格体

学习笔记&#xff0c;仅供参考&#xff01; 一、完成创建关卡和AI代理的初步步骤&#xff0c;以演示可以修改导航系统的不同方法。 创建简单关卡&#xff0c;并通过在关卡中放入导航网格体边界体积Actor来添加导航。 将ThirdPersonCharacter蓝图修改为使用导航系统在关卡中四…

vuepress-theme-vdoing博客搭建教程

搭建流程 前言 这是笔者搭建个人博客所经历的流程&#xff0c;特附上笔记 笔者个人博客地址&#xff1a;沉梦听雨的编程指南 一、主题介绍 本博客使用的主题为&#xff1a;vuepress-theme-vdoing&#xff0c;相关介绍和使用方法可以参考该主题的官方文档 官方文档快速上手…

力扣趣味题:找不同

经典面向样例编程 char findTheDifference(char* s, char* t) {if(sNULL){return t[0];}for(int x0;x<strlen(s);x){for(int y0;y<strlen(t);y){if(s[x]t[y]){t[y]1;break;}}}for(int x0;x<strlen(t);x){if(t[x]!1){return t[x];}}return NULL; }

银发经济@315:消费、陷阱与孤独的老人

【潮汐商业评论/文】 又是一年315。 这一天&#xff0c;从品牌到消费者&#xff0c;从线下到网络&#xff0c;都不约而同地将目光锁定在大众消费生活和与其相伴的消费“陷阱”上。 这其中&#xff0c;作为“有闲又有钱”且与社会经济发展速度相对有一定“代沟”的老年消费者群…

新加坡大带宽服务器托管优势

在数字化快速发展的今天&#xff0c;服务器托管成为企业拓展业务、提高服务质量的关键环节。而新加坡作为一个国际性的金融、贸易和科技创新中心&#xff0c;其大带宽服务器托管服务在全球范围内享有盛誉。本文将为您科普新加坡大带宽服务器托管的诸多优势。 首先&#xff0c;新…

AXI CANFD MicroBlaze 测试笔记

文章目录 前言测试用的硬件连接Vivado 配置Vitis MicroBlaze CANFD 代码测试代码测试截图Github Link 前言 官网: CAN with Flexible Data Rate (CAN FD) (xilinx.com) 特征: 支持8Mb/s的CANFD多达 3 个数据位发送器延迟补偿(TDC, transmitter delay compensation)32-deep T…

VS Code上,QT基于cmake,qmake的构建方法(非常详细)

VS Code上,QT基于cmake&#xff0c;qmake的构建方法 1 前言2 QT基于cmake的构建方法2.1 VS Code关键插件安装2.2 系统环境变量配置2.3 VS Code中&#xff0c;环境变量配置2.4 Cmake新建一个新的Porject 3 QT基于qmake的构建方法 1 前言 最近&#xff0c;由于认证了github的学生…

RabbitMQ学习总结-延迟消息

1.死信交换机 一致不被消费的信息/过期的信息/被标记nack/reject的信息&#xff0c;这些消息都可以进入死信交换机&#xff0c;但是首先要配置的有私信交换机。私信交换机可以再RabbitMQ的客户端上选定配置-dead-letter-exchange。 2.延迟消息 像我们买车票&#xff0c;外卖…

PHP 生成图片

1.先确认是否有GD库 echo phpinfo(); // 创建一个真彩色图像 $image imagecreatetruecolor(120, 50);// 分配颜色 $bgColor imagecolorallocate($image, 255, 255, 255); // 白色背景 $textColor imagecolorallocate($image, 230, 230, 230); // 黑色文字// 填充背景 image…

MyFileServer

靶场下载地址 https://download.vulnhub.com/myfileserver/My_file_server_1.ova 信息收集 # nmap -sn 192.168.56.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-24 22:07 CST Nmap scan report for 192.168.56.2 (192.168.56.2) Host is up (0.…

Java学习笔记(13)

阶段项目 拼图小游戏 JFrame JMenuBar JMenu JMenuItem 用add方法添加到不同的对象中 添加图片 先创建一个图片ImageIcon的对象&#xff0c;写入图片的路径 再创建JLabel管理容器对象&#xff0c;把图片放到这个容器中&#xff0c;再把容器添加到界面 界面坐标位置 改变图…