代码随想录算法训练营Day27 | 回溯算法理论基础、77.组合、216.组合总和Ⅲ、17.电话号码的字母组合

news2024/12/26 21:28:38

目录

回溯算法理论基础

77.组合

216.组合总和Ⅲ

17.电话号码的字母组合

回溯算法理论基础

视频讲解:带你学透回溯算法(理论篇)| 回溯法精讲!

代码随想录:回溯算法理论基础

回溯函数与递归函数指的是同一个函数,回溯的本质是穷举所有可能,最后得到想要的答案。

回溯法可用于解决如下问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 棋盘问题:N皇后,解数独等等

注:组合无序,排列有序

回溯法解决的问题可以抽象为树形结构,因为回溯法解决的都是在集合中递归查找子集的问题,集合的大小就构成了树的宽度,递归的深度就构成了树的深度

回溯算法代码模板如下:

void backtrack(参数) {
    if (满足终止条件) {
        //记录结果
        return;
    }
    for (选择 : 当前所有可能的选择) {
        // 处理节点
        修改当前状态;
        // 递归地进行下一步选择
        backtrack(路径, 新的参数);
        // 回溯
        恢复到之前的状态;
    }
}

77.组合

题目

77. 组合 - 力扣(LeetCode)

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

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

示例1:

输入:n = 4, k = 2
输出:
[
  [2,4],
  [3,4],
  [2,3],
  [1,2],
  [1,3],
  [1,4],
]

示例2:

输入:n = 1, k = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
  • 1 <= k <= n

思路

视频讲解:LeetCode:77.组合

视频讲解:LeetCode:77.组合 剪枝优化

代码随想录:77.组合

如果解决一个问题有多个步骤,每一个步骤有多种方法,题目中找出所有的方法,可以使用回溯算法,回溯算法是在一棵树上的 深度优先遍历

组合问题不要求一个组合内元素的顺序,因此很多时候需要按某种顺序展开搜索,才能做到不重不漏。

回溯算法首先需要画出递归树,如图:

77.组合

n相当于数的宽度,k相当于树的深度,每当搜索到叶子节点,就得到一个结果。

剪枝优化: 当 n = 4,k = 4 时,第一层for循环时从元素2开始的遍历就没有意义了,如图:

77.组合4

图中每一个节点代表本层的一个for循环,每一层的for循环从第二个数开始的遍历都是无效遍历。

所以,可以剪枝的地方就在递归中每一层的for循环所选择的起始位置,如果for循环选择的起始位置之后的元素个数少于需要的元素个数,就没有必要继续搜索了。

题解

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> combine(int n, int k) {
        backtracking(n, k, 1);
        return res;
    }

    void backtracking(int n, int k, int startIndex) {
        if (path.size() == k) {
            res.add(new ArrayList<>(path));
            return;
        }
        //优化处,原为 i <= n
        for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) {
            path.add(i);
            backtracking(n, k, i + 1);
            path.removeLast();
        }
    }
}

216.组合总和Ⅲ

题目

216. 组合总和 III - 力扣(LeetCode)

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

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

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

示例1:

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

示例2:

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

示例3:

输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

提示:

  • 2 <= k <= 9
  • 1 <= n <= 60

思路

代码随想录:216.组合总和Ⅲ

视频讲解:LeetCode:216.组合总和Ⅲ

216.组合总和III

剪枝有两种情况:

  1. 剩余和小于当前数
  2. 剩余元素不足以满足组合数量

题解

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> combinationSum3(int k, int n) {
        backtrack(k, n, 1);
        return res;
    }

    void backtrack(int k, int n, int startIndex) {
        if (path.size() == k) {
            if (n == 0)
                res.add(new ArrayList(path));
            return;
        }
        for (int i = startIndex; i <= 9; i++) {
            if (n < i || path.size() + (9 - i + 1) < k) {
                break; // 剪枝:如果剩余和小于当前数,或者剩余元素不足以满足组合数量,直接跳出循环
            }
            path.add(i);
            backtrack(k, n - i, i + 1);
            path.removeLast();
        }
    }
}

17.电话号码的字母组合

题目

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

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

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

img

示例1:

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

示例2:

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

示例3:

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

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

思路

代码随想录:17.电话号码的字母组合

视频讲解:LeetCode:17.电话号码的字母组合

使用 HashMap 存放数字和字母之间的映射。

树形结构如下:

17. 电话号码的字母组合

题解

class Solution {
    List<String> res = new ArrayList<>();
    StringBuilder sb = new StringBuilder();

    public List<String> letterCombinations(String digits) {
        //digits为空字符串时返回null
        if (digits.length() == 0)
            return res;
        Map<Character, String> map = Map.of(
                '2', "abc",
                '3', "def",
                '4', "ghi",
                '5', "jkl",
                '6', "mno",
                '7', "pqrs",
                '8', "tuv",
                '9', "wxyz"
        );
        backtrack(digits, 0, map);
        return res;
    }

    void backtrack(String digits, int index, Map<Character, String> map) {
        if (index == digits.length()) {
            res.add(sb.toString());
            return;
        }
        char ch = digits.charAt(index);
        String str = map.get(ch);
        
        for (int i = 0; i < str.length(); i++) {
            sb.append(str.charAt(i));
            backtrack(digits, index + 1, map);
            sb.deleteCharAt(sb.length() - 1);
        }
    }
}

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

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

相关文章

VSCode | 设置Jupyter Notebook显示行号

vscode中的jupyter notebook每个cell都是默认不显示行号的&#xff0c;如果出现了报错&#xff0c;比如在52行出现报错&#xff0c;如果代码多的话不显示行号就有点麻烦&#xff0c;本文介绍如何设置显示行号。 1、VScode点击文件-首选项-设置 2、搜索“python”&#xff0c;点…

Type-C那么多引脚是做什么用的?

一提到Type-C大家想到的肯定就是下面这个扁头接口。 如果大家仔细透过缝看里面的话&#xff0c;可以看到上下两排都有密密麻麻的引脚&#xff08;手机比较差拍不出来就不上图了&#xff09;。 虽然我们用Type-C口的时候我们不需要识别正反面&#xff08;这也是我喜欢Type-C的…

基于Java语言的充电桩平台+云快充协议+充电桩管理后台+充电桩小程序

软件架构 1、提供云快充底层桩直连协议&#xff0c;版本为云快充1.5&#xff0c;对于没有对接过充电桩系统的开发者尤为合适&#xff1b; 2、包含&#xff1a;启动充电、结束充电、充电中实时数据获取、报文解析、Netty通讯框架、包解析工具、调试器模拟器软件等&#xff1b;…

电脑提示d3dcompiler_47.dll缺失怎么修复,仔细介绍dll的解决方法

1. d3dcompiler_47.dll 概述 1.1 定义与作用 d3dcompiler_47.dll 是 Microsoft DirectX 的一个关键组件&#xff0c;作为一个动态链接库&#xff08;DLL&#xff09;文件&#xff0c;它在 Windows 操作系统中扮演着至关重要的角色。DirectX 是一套由微软开发的用于处理多媒体…

Flutter渲染过程

The rendering process is what transforms your widget tree into the actual pixels that are displayed on the screen. It’s like the magic behind the scenes that brings your app’s UI to life! 呈现过程将小部件树转换为显示在屏幕上的实际像素。它就像幕后的魔法&…

代码随想录算法训练营第二十六天|669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树

669. 修剪二叉搜索树 给定一个二叉搜索树&#xff0c;同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[L, R]中 (R>L) 。你可能需要改变树的根节点&#xff0c;所以结果应当返回修剪好的二叉搜索树的新的根节点。 思路&#xff1a; 首先…

JavaScript 获取浏览器本地数据的4种方式

JavaScript 获取浏览器本地数据的方式 我们在做Web开发中&#xff0c;客户端存储机制对于在浏览器中持久化数据至关重要。这些机制允许开发者存储用户偏好设置、应用状态以及其他关键信息&#xff0c;从而增强用户体验。本文将介绍几种常用的JavaScript获取浏览器本地数据的方…

【无人机设计与控制】基于蜣螂优化算法的无人机三维路径规划Matlab程序

摘要 使用蜣螂优化算法&#xff08;Dung Beetle Optimization, DBO&#xff09;&#xff0c;本文提出了一种无人机三维路径规划方法。该算法借鉴蜣螂导航行为&#xff0c;结合无人机避障需求&#xff0c;在复杂三维环境中生成最优路径。实验结果表明&#xff0c;基于DBO的路径…

Redis主从复制(replica)、哨兵

一、Redis主从复制介绍: 主从复制&#xff0c;master主机以写为主&#xff0c;slave从机以读为主&#xff0c;当主机数据变化的时候自动将新的数据异步同步到其他从机数据库&#xff1b;能够实现读写分离&#xff0c; 容灾恢复、 数据备份以及水平扩容支撑高并发 二、实现方法…

在ubuntu好部署jenkins发布vue项目时遇到的一些问题及解决方法以及使用jenkins发布vue项目-npm自动打包发布的实现

一、在ubuntu好部署jenkins发布vue项目时遇到的一些问题及解决方法 1. 问题&#xff1a;webpack-dev-server不是内部或外部命令&#xff0c;也不是可运行的程序 解决&#xff1a;使用webpack要安装webpack-cli这个包&#xff0c;才可以调用webpack和webpack-dev-server这些命…

C++——模拟实现stack和queue

1.传统模拟方式 namespace jxy {template<class T>class stack{//...private:T* _a;size_t _size;size_t _capacity;}; } 2.适配器方式模拟 namespace jxy {template<class T,class Container>class stack{public:void push(const T& x){_con.push_back(x);…

No.6 笔记 | Linux操作系统基础:全面概览与核心要点

1. 简介与历史 1.1 起源 创始人&#xff1a;Linus Torvalds&#xff08;芬兰赫尔辛基大学学生&#xff09;初衷&#xff1a;设计一个替代Minix的全功能Unix操作系统首次发布&#xff1a;1991年10月5日&#xff0c;Linux v0.01版本 2. Linux特点 多用户多任务&#xff1a;用…

【Python】PDFMiner.six:高效处理PDF文档的Python工具

PDF是一种广泛使用的文件格式&#xff0c;特别适用于呈现固定布局的文档。然而&#xff0c;提取PDF文件中的文本和信息并不总是那么简单。幸好有许多Python库可以帮助我们&#xff0c;其中&#xff0c;PDFMiner.six 是一个功能强大、专门用于PDF文档解析的库。 ⭕️宇宙起点 &a…

计算机毕业设计 基于Python的老年人健康预警系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

数据仓库拉链表

数仓拉链表是数据仓库中常用的一种数据结构&#xff0c;用于记录维度表中某个属性的历史变化情况。在实际应用中&#xff0c;数仓拉链表可以帮助企业更好地进行数据分析和决策。 数仓拉链表&#xff08;Slowly Changing Dimension, SCD&#xff09;是一种用于处理维表中数据变化…

Linux驱动开发——新字符设备驱动开发

文章目录 1 概述2 新字符设备驱动原理2.1 分配和释放设备号2.2 新字符设备注册方法 3 自动创建设备节点3.1 mdev机制3.2 创建和删除类3.3 创建设备 4 设置文件私有数据5 实验程序编写 系列文章&#xff1a; Linux驱动开发——字符设备驱动开发 Linux驱动开发——LED驱动开发 1 …

24最新从零开始教你玩转ComfyUI-保姆级部署教程-手把手带你ComfyUI工作流搭建!

前言 第一节&#xff1a;认识ComfyUI并安装 本教程专为初学者设计&#xff0c;详细介绍了 2024 年最新版的SD ComfyUI的使用方法。通过逐步指导&#xff0c;让你无需任何基础&#xff0c;快速学会并使用这一强大的AI绘图工具。 1、什么是comfyui ComfyUI就像拥有一支神奇魔…

如何定位前后端Bug?

问题&#xff1a; 假设你在某购物网站上&#xff0c;购买了两件商品&#xff0c;一件打折的&#xff0c;一件不打折的&#xff0c;当你下完订单并且成功支付之后&#xff0c;再去我的订单中查看订单内容时&#xff0c;发现两件商品只显示出来一件&#xff0c;打折的商品并没有显…

最强AI绘画大模型Flux可以在SDWebUI 上使用了!超便捷的Flux模型使用教程!AI绘画零基础入门到实战教程

大家好&#xff0c;我是画画的小强 目前最强的AI绘画大模型Flux.1 横空出世有段时间了&#xff0c;模型效果也得到了广泛的认可&#xff0c;但是 Stable Diffusion WebUI 官方迟迟没有跟进&#xff0c;据说是因为要修改很多底层的处理机制&#xff0c;加之ComfyUI如火如荼&…

基于Springboot的宠物咖啡馆平台的设计与实现(源码+定制+参考)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…