代码随想录算法训练营第二十二天| 回溯算法理论基础 77. 组合 216.组合总和III 17.电话号码的字母组合

news2024/9/29 3:32:09

目录

  • 一、回溯算法理论基础
  • 二、LeetCode 77. 组合
    • 思路
    • C++代码
  • 二、LeetCode 216.组合总和III
    • 思路
    • C++代码
  • 二、LeetCode 17.电话号码的字母组合
    • 思路
    • C++代码
  • 总结


一、回溯算法理论基础

回溯法:回溯法是一种将问题遍历的结构抽象为树形结构,在解空间树种采取深度优先策略,系统地搜索问题的所有解。

 简单地来说,回溯法是一种在解空间树内暴力搜索的算法。可通过限界函数进行剪枝来提升算法效率。

 回溯法在问题没有更优解法的时候,适用于求解答案是向量的问题,如搜索问题、排序问题、优化问题等。

 回溯法的搜索空间是由问题的解构成的解空间树,常见的类型有:子集树、排列树、搜索树。

二、LeetCode 77. 组合

题目链接:LeetCode 77. 组合

文章讲解:代码随想录
视频讲解:带你学透回溯算法-组合问题(对应力扣题目:77.组合)| 回溯法精讲!

思路

 一招鲜,吃遍天。组合问题是回溯法的经典题目,也可以作为所有回溯法(子集树)的一个代码模板来写。

 要求在 1 ∼ n 1\sim n 1n 中取出所有可能的组合,涉及到我们每一步选择哪个数加入组合的问题。在每一步(每一层)选择每个可能的数(遍历孩子结点)就可以抽象为一个子集树的遍历过程,于是可以使用回溯算法进行遍历求解。
在这里插入图片描述
 在回溯过程中,重要的部分在于如何表述每一层中选择不同孩子的逻辑,以及遍历子集树时进入下一层遍历的传参问题。如上图,在本问题中,我们将当前位置选择哪一个数作为不同的孩子结点,那么我们可以写一个for循环来完成不同孩子结点之间的遍历,用递归实现进入下一层:

for(int i = pre + 1; i <= n; i++){  //递归构建子集树
    set[t] = i;
    backtrack(t+1, i, n, k, set);
}

set使用全局变量的话可以这样写:

for (int i = startIndex; i <= n; i++) { // 控制树的横向遍历
    path.push_back(i); // 处理节点
    backtracking(n, k, i + 1); // 递归:控制树的纵向遍历,注意下一层搜索要从i+1开始
    path.pop_back(); // 回溯,撤销处理的节点
}

 这样更为规范,可读性也更好一些。

 终止条件设置为set中元素数量等于k即可。

 在上述代码的基础上,可以做一定的剪枝提高时间效率:我们可以发现,在前一位数选择了n-(k-set.size())+1时,即前面数选择以后,后面的数不够分,达不到k个的数目,那么这些分支实际上都是无效遍历;也就是说,在组合中,每一位上选择的数是有一个右边界的,我们通过找规律不难发现,这个右边界就是n-(k-set.size())+1
在这里插入图片描述
 那么遍历代码可以优化为:

for (int i = startIndex; i <= n - (k - set.size()) + 1; i++) // i为本次搜索的起始位置

C++代码

class Solution {
public:
    vector<vector<int>> subsets;

    void backtrack(int t, int pre, int n, int k, vector<int> set){
        if(t == k){
            subsets.push_back(set);
            return;
        } 
        for(int i = pre + 1; i <= n-(k-t)+1; i++){  //递归构建子集树
            set[t] = i;
            backtrack(t+1, i, n, k, set);
        }
    }

    vector<vector<int>> combine(int n, int k) {
        vector<int> set(k);
        backtrack(0, 0, n, k, set);
        return subsets;
    }
};

二、LeetCode 216.组合总和III

题目链接:LeetCode 216.组合总和III

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

思路

 本题与上题较为相似,不同之处只在于使用数字变为一到九,并增加一个总和条件。我们只调节可选取的数字,并增加一个总和相等的终止条件即可。

C++代码

class Solution {
private:
    vector<vector<int>> sumsets;
    vector<int> set;

    void backtrack(int pre, int sum, int k, int n){
        if(sum > n) return; //剪枝操作:总和大于要求值返回
        if(set.size() == k){ //终止条件
            if(sum == n){
                sumsets.push_back(set);
            }
            return;
        }
        for(int i = pre + 1; i <= 9-(k-set.size())+1; i++){ //数字选取1--9
            set.push_back(i);
            sum += i;
            backtrack(i, sum, k, n);
            sum -= i;
            set.pop_back();
        }
    }
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        backtrack(0, 0, k, n);
        return sumsets;
    }
};

二、LeetCode 17.电话号码的字母组合

题目链接:LeetCode 17.电话号码的字母组合

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

思路

 本题也是很简单的组合问题,主要解决的点在于电话号码上字母的映射,可以选择建立一个全局变量数组存储每个数字对应的字母,笔者采用 A S C I I ASCII ASCII 码转换的方法进行映射。其余操作与基本的回溯法相同。

C++代码

class Solution {
private:
    vector<string> combinations;
    string letters;

    void backtrack(string digits, int index){
        if(index == digits.size()){
            combinations.push_back(letters);
            return;
        }

        int del = 3;
        int be;

        if(digits[index] > '1' && digits[index] < '7'){
            be = 43 + int(digits[index]-'0') * 2;
        }
        else if(digits[index] == '7'){
            be = 57;
            del = 4;
        }
        else if(digits[index] == '8'){
            be = 60;
        }
        else if(digits[index] == '9'){
            be = 62;
            del = 4;
        } 

        for(int i = be; i < be+del; i++){
            letters.push_back(digits[index] + i);
            backtrack(digits, index+1);
            letters.pop_back();
        }
    }
public:
    vector<string> letterCombinations(string digits) {
        if(digits.empty()) return combinations;
        backtrack(digits, 0);
        return combinations;
    }
};


总结

 回溯法章节开始,逐渐开始正式复习算法设计课的知识。


文章图片来源:代码随想录 (https://programmercarl.com/)

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

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

相关文章

vxe-selectvxe-date-picker下拉框被遮问题

解决之法&#xff1a; html: // vxe-select组件 &#xff0c;要加transfer <vxe-select:placeholder"$t(button.selects)"v-model"item.ruleParamId":options"item.options?.map(val > ({label: val.paramName, value: val.id}))"chang…

【操作系统 / 系统编程】2025 秋招超详细复习指南 - 基于 Linux 环境的全面复习 - 持续更新(目前1.7w字)

操作系统 / 系统编程复习目录 一、进程概念1. 冯诺依曼1.1 外设1.2 IO1.3 数据流1.4 存储分级 && IO效率 2. OS2.1 作用&#xff1a;管理2.2 管理&#xff1a;先描述&#xff0c;再组织2.3 内存管理、进程管理、文件系统、驱动管理 3. 进程3.1 什么是进程3.2 为什么要有…

数学建模2024国赛时间及事项安排

2024年的全国大学生数学建模竞赛即将拉开帷幕。考虑到许多同学可能是首次参与此类赛事&#xff0c;尚不清楚如何进行有效的时间安排&#xff0c;博主在此整理了以往参赛的经验和时间管理策略&#xff0c;希望能为大家提供一些有益的参考&#xff0c;更从容地应对国赛。 本届全国…

定制开发AI智能名片商城小程序:重塑品牌曝光的创新推手

摘要&#xff1a;随着移动互联网技术的飞速发展&#xff0c;小程序作为一种轻量级应用形态&#xff0c;正逐步成为企业品牌传播与商业变现的重要渠道。本文将探讨在品牌定位中&#xff0c;如何将“定制开发AI智能名片商城小程序”作为品牌曝光的核心推手&#xff0c;通过强化品…

pikachu-Cross-Site Scripting通过攻略

反射型xss(get) 第一步&#xff1a;进入先将maxlength中的20修改大一些&#xff0c;以便我们可以输入更多的字符 第二步&#xff1a;输入<script>alert(1)</script>成功爆破 反射型xss(post) 第一步&#xff1a;点击提示得到用户名和密码登录 第二步&#xff1…

轻松备份和共享照片的Circled.me

什么是 Circled.me &#xff1f; Circled.me 旨在帮助人们在自己的服务器上轻松备份和共享照片、视频、相册。注重性能、低占用空间以及易于实施和使用。支持托管社区所需的一切&#xff0c;能够进行交流和交换照片、想法等&#xff0c;实现通过群聊等方式与您的圈子分享。 软件…

电脑资料被删除怎么办?这些方法帮你轻松找回!

在日常工作和生活中&#xff0c;电脑资料的安全存储至关重要。然而&#xff0c;有时我们可能会因为误操作或其他原因不小心删除了重要资料。这时&#xff0c;我们该如何应对呢&#xff1f;本文将为你提供几种有效的恢复方法&#xff0c;帮你轻松找回被删除的电脑资料。 一、撤…

MySQL如何判断一个字段里面是否包含汉字

SQL查询中&#xff0c;length() 和 char_length() 都是用来获取字符串长度的函数 在单字节字符集下&#xff08;如ASCII&#xff09;&#xff1a;每个字符通常占用1个字节&#xff0c;因此length()和char_length()在这类字符集中给出的结果是一样 在多字节字符集下&#xff0…

湖北省各市各地两化融合贯标、3A级认定申报奖补补助、申报条件材料、流程指南

盘点湖北省各市各地两化融合贯标、3A级认定申报奖补补助、申报条件材料、流程等内容&#xff0c;武汉市、黄石市、十堰市、宜昌市、襄阳市、鄂州市、荆门市、孝感市、荆州市、黄冈市、咸宁市、随州市,恩施土家族苗族自治州、仙桃市、潜江市、天门市、神农架林区有需要具体了解的…

OPPO手机短信删除了怎么恢复?三大解决办法助你找回

在快节奏的生活中&#xff0c;手机短信作为我们日常沟通的重要工具之一&#xff0c;往往承载着许多重要的信息&#xff0c;如验证码、银行通知、会议安排等。然而&#xff0c;不小心误删短信的情况时有发生&#xff0c;特别是对于OPPO手机用户而言&#xff0c;短信一旦删除&…

谷粒商城实战笔记-240~243-商城业务-购物车-页面环境搭建

文章目录 一&#xff0c;页面调整1&#xff0c;详情页增加“加入购物车”按钮 二&#xff0c;添加购物车后台实现详细步骤异步处理的优点 三&#xff0c;解决加购重复提交问题 这部分的主要内容&#xff1a; 从product模块的详情页点击加入购物车&#xff0c;发送请求到cart购物…

Kubernetes服务发布基础

一、Service 1.service基本介绍 service为一组提供服务的pod提供抽象的稳定的网络访问地址&#xff0c;主要用于网络服务&#xff0c;通过service定义&#xff0c;为客户端提供访问地址和负载均衡&#xff0c;屏蔽endport的变化。 在 kubernetes 中,pod 的IP 地址是动态变…

大数据面试-Zookeeper

你对Zookeeper的选举机制了解吗&#xff1f;为什么zk节点个数推荐奇数台&#xff1f;zk第一次启动的选举的细节了解吗&#xff1f; ‌ZooKeeper的选举机制‌是基于Paxos算法的一种分布式选举算法&#xff0c;用于在ZooKeeper集群中选择一个节点作为Leader&#xff0c;负责处理…

做外贸如何判断国外采购商公司规模

判断客户公司的规模&#xff0c;对于业务员来说很重要&#xff0c;这样在谈价格以及其他条款的时候才能掌握主动。一般要怎么去判断客户公司的规模呢?我们都是做实事的&#xff0c;实际经验很重要&#xff0c;做过和没做过的看多了就知道。最基本的信息是公司的注册时间及相关…

【python】Python中通过WHL文件离线安装需要的包最全面讲解

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【oracle】工具访问oracle提示-IO 错误: Got minus one from a read call

问题描述&#xff1a; 使用工具访问数据库时&#xff0c;提示IO 错误: Got minus one from a read call&#xff0c;在服务器上检查数据库正常&#xff0c;监听正常&#xff0c;连接数合理&#xff0c;防火墙没限制。最后定位sqlnet.ora配置限制了客户端访问。 解决&#xf…

四川财谷通信息技术有限公司解锁抖音小店新机遇

在数字经济蓬勃发展的今天&#xff0c;电商平台已成为推动商业创新、促进消费升级的重要力量。其中&#xff0c;抖音小店凭借其庞大的用户基础、精准的算法推荐以及高度活跃的社区氛围&#xff0c;迅速崛起为众多商家青睐的创业与营销新阵地。四川财谷通信息技术有限公司&#…

Groovy DSL从入门到项目实战(一)

Groovy是一门很灵活的Java扩展语言&#xff0c;支持弱类型、闭包、函数式编程等脚本语言的高级特性。因为小卷所在公司的船申报系统需要重构&#xff0c;对原先java硬编码的各种表单数据校验、后台业务校验使用规则脚本的形式进行剥离出来。而市面上像Jboss Drools这样的规则引…

docker-compose安装sentry

官方文档 https://develop.sentry.dev/self-hosted/ 一、前提 服务器配置至少4C16G&#xff0c;否则起不来 二、安装docker https://blog.csdn.net/weixin_45112997/article/details/134532660 三、安装docker-compose docker-compose版本有要求&#xff0c;必须大于2.…

ISO7841标准数字隔离器在现代电子系统中的作用

在快速发展的电子领域&#xff0c;隔离元件在确保各种系统的安全性、可靠性和性能方面发挥着关键作用。其中&#xff0c;光耦合器是提供电气隔离同时允许电路不同部分之间进行信号传输的关键设备。ISO7841数字隔离器尤其体现了现代电子设计所需的先进功能和多功能性。 ISO7841数…