算法 DAY24 回溯 || 第77题. 组合 216.组合总和III 17.电话号码的字母组合 39. 组合总和

news2025/1/24 11:28:50

前置知识

回溯算法模板框架如下:

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

注意这里的for,回溯问题可以看成树问题,但是N叉树,
而不一定是二叉树。

看一下589.N叉树的前序遍历就很好理解了
在这里插入图片描述

class Solution {
public:
    vector<int> res;
    vector<int> preorder(Node* root) {
        traversal(root);
        return res;
    }
    void traversal(Node* root){
        if(root == nullptr) return ;
        res.push_back(root->val);
        for(int i = 0; i < root->children.size(); ++i){
            traversal(root->children[i]);
        }
    }
};

对于组合问题,什么时候需要startIndex呢?

我举过例子,如果是一个集合来求组合的话,就需要startIndex, 例如:77.组合
(opens new window),216.组合总和III

(opens new window)。

如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:17.电话号码的字母组合

第77题. 组合

不难 按照模板的思路来,考虑成N叉树的层序遍历就行。
当k = 2, n = 4时
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> res;
    vector<int> vec;
    vector<vector<int>> combine(int n, int k) {
        backtracking(n,k,vec,1);
        return res;
    }
    void backtracking(int n,int k,vector<int>& vec,int start){
        if(vec.size() == k) {
            res.push_back(vec);
            return;
        }
        for(int i = start; i <= n; ++i){
            vec.push_back(i);
            backtracking(n,k,vec,i+1);
            vec.pop_back();
        }
    }
};

接下来看一下优化过程如下:
1、已经选择的元素个数:path.size();
2、还需要的元素个数为: k - path.size();
3、在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历

为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。

举个例子,n = 4,k = 3, 目前已经选取的元素为0(path.size为0),n - (k - 0) + 1 即 4 - ( 3 - 0) + 1 = 2。

从2开始搜索都是合理的,可以是组合[2, 3, 4]。

这里大家想不懂的话,建议也举一个例子,就知道是不是要+1了。

所以优化之后的for循环是:

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

216.组合总和III

不难,但是递归的时候要注意是 i+1,而不是start+1;

class Solution {
public:
    vector<vector<int>> res;
    vector<int> vec;
    vector<vector<int>> combinationSum3(int k, int n) {
        backtracking(k,n,1);
        return res;
    }
    void backtracking(int k, int n, int start){
        int sum = 0;
        for(int a : vec) sum += a;
        if(vec.size() == k && sum == n) {
            res.push_back(vec);
            return;
        }

        for(int i = start; i <= 9 && vec.size() < k && i + sum <= n ; ++i){           
            vec.push_back(i);
            backtracking(k,n,i+1);
            vec.pop_back();
        }
    }
};

17.电话号码的字母组合

电话号码的数字和字符串对应可以直接用数组来解决。另外index一定是整数,注意数据类型之间的转换
本题的广度就是 数字对应字符串的长度。深度是digits的长度

class Solution {
public:
    string phone[10] = {
        "0",
        "0",
        "abc",
        "def",
        "ghi",
        "jkl",
        "mno",
        "pqrs",
        "tuv",
        "wxyz"
    };
    vector<string> res;
    vector<char> vec;
    vector<string> letterCombinations(string digits) {
        if(digits.size() == 0) return res;
        backtracking(digits,0);
        return res;
    }
    void backtracking(string digits,int start){
        if(vec.size() == digits.size()){
            string str = "";
            for(char c : vec) str += c;
            res.push_back(str);
            return;
        }
        for(int i = start; i < digits.size(); ++i){ //这一层for其实没有必要,本题的广度就是 数字对应字符串的长度。深度是digits的长度
            //digits[i] 是char类型 但是index一定是int
            int index = digits[i] - '0';
            for(int j = 0; j < phone[index].size(); ++j){
                vec.push_back(phone[index][j]);
                backtracking(digits,i+1);
                vec.pop_back();
            }
        }
    }
};

39. 组合总和

注意去重,要重新再写一遍

class Solution {
public:
    vector<vector<int>> res;
    vector<int> vec;
    int sum = 0;
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
        backtracking(candidates,target,0);
        return res;
    }
    void backtracking(vector<int> candidates,int target,int start){
        if(sum > target) return;
        if(sum == target) res.push_back(vec);

        for(int i = start; i < candidates.size(); ++i){
            vec.push_back(candidates[i]);
            sum += candidates[i];
            if(sum > target){
                sum -= candidates[i];
                vec.pop_back();
                break;
            }
            backtracking(candidates,target,i);
            sum -= candidates[i];
            vec.pop_back();
        }
    }
};

40.组合总和II

去重的时候也可以用used数组

class Solution {
public:
    vector<vector<int>> res;
    vector<int> vec;
    int sum = 0;
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
        backtracking(candidates,target,0);
        return res;
    }
    void backtracking(vector<int>& candidates,int target,int start){
        if(sum > target) return;
        if(sum == target) res.push_back(vec);

        for(int i = start; i < candidates.size() && sum + candidates[i] <= target; ++i){
            if(i > start && candidates[i-1] == candidates[i]) continue;
            vec.push_back(candidates[i]);
            sum += candidates[i];
            backtracking(candidates,target,i+1);
            sum -= candidates[i];
            vec.pop_back();
        }
    }
};

131.分割回文串

自己写出来的AC了,但是可以优化。
优化点:
1、使用startIndex来区分切割区间
2、直接判断当前字符串是否是回文,再看下一步是否递归

class Solution {
public:
    vector<vector<string>> res;
    vector<string> vec;
    vector<vector<string>> partition(string s) {
        backtracking(s);
        return res;
    }
    void backtracking(string s){
        if("" == s){
            bool bres = hui(vec);
            if(bres == true) res.push_back(vec);
            else return;
        }
        for(int i = 0; i < s.size(); ++i){
            vec.push_back(string(s.begin(),s.begin()+i+1));
            backtracking(string(s.begin()+i+1,s.end()));
            vec.pop_back();
        }
    }
    bool hui(vector<string>& vec){
        for(string s : vec){
            int left = 0;
            int right = s.size()-1;
            for(int i = left,j = right; i < j; ++i,--j){
                if(s[i] != s[j]) return false;
            }
        }
        return true;
    }
};

优化代码:

class Solution {
public:
    vector<vector<string>> res;
    vector<string> vec;
    vector<vector<string>> partition(string s) {
        backtracking(s,0);
        return res;
    }
    void backtracking(string s,int start){
        if(start >= s.size()){
            res.push_back(vec);
            return;
        }
        for(int i = start; i < s.size(); ++i){
            string str(s.begin()+start,s.begin()+i+1);
            bool bres = hui(str);
            if(bres == false) continue; 
            //直接在这一步判断,也起到一个剪枝的效果
            vec.push_back(str);
            backtracking(s,i+1);
            vec.pop_back();
        }
    }
    bool hui(string s){
        int left = 0;
        int right = s.size()-1;
        for(int i = left,j = right; i < j; ++i,--j){
            if(s[i] != s[j]) return false;
        }
        return true;
    }
};

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

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

相关文章

rk3568点亮LCD(lvds)

rk3568 Android11/12 适配 lvds 屏 LVDS&#xff08;Low Voltage Differential Signal&#xff09;即低电压差分信号。1994年由美国国家半导体&#xff08;NS&#xff09;公司为克服以TTL电平方式传输宽带高码率数据时功耗大、电磁干扰大等缺点而研制的一种数字视频信号传输方…

堆的实现

思维导图 堆的概念 普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储&#xff0c;需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事…

【LeetCode】剑指 Offer 50. 第一个只出现一次的字符 p243 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/ 1. 题目介绍&#xff08;50. 第一个只出现一次的字符&#xff09; 在字符串 s 中找出第一个只出现一次的字符。如果没有&#xff0c;返回一个单空格。 s 只包含小写字母。 【测…

al文章生成-文章生成工具

ai文章生成器 AI文章生成器是一种利用人工智能和自然语言处理技术生成文章的工具。它使用先进的算法、机器学习和深度学习技术&#xff0c;深度挖掘和提取大量数据背后的信息&#xff0c;自主学习并合并新的信息&#xff0c;生成优质、原创的文章。 使用AI文章生成器的优点如下…

liunx mysql 主从同步设置 关键点

主库MySQL配置文件&#xff1a;该配置文件默认是在 /etc/my.cnf [mysqld] max_allowed_packet256M server-id1 log-binmysql-bin replicate-do-dbweb auto_increment_increment2 auto_increment_offset1 binlog_ignore_dbsys general_logon general_log_file/v…

Qt下载以及调试

1.概念 Qt是一个跨平台的基于C图形用户界面应用程序框架。 常见GUI&#xff1a; Qt&#xff1a;支持多平台&#xff1b;支持css&#xff1b;面向对象特性体现突出&#xff1b;发展趋势良好&#xff1b; MFC&#xff1a;仅在Windows&#xff1b;运行程序效率高&#xff1b;库安…

外包干了四年,感觉废了..

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

如何利用ventoy制作Linux to go (把deepin放到U盘里)

准备工作 最新版本 – 深度科技社区 (deepin.org) deepin镜像官方下载即可 Releases ventoy/vtoyboot GitHub ventoy启动插件选择1.0.29版本 Downloads – Oracle VM VirtualBox VirtualBox虚拟机官网 ventoy下载 VentoyRelease (lanzoui.com) 选择下载1.0.29版本 vento…

表格软件界的卷王,Excel、access、foxpro全靠边,WPS:真荣幸

Excel和Access就是表格软件的选择&#xff1f; 现在&#xff0c;铺天盖地的Excel的技能教程可谓是满天飞&#xff0c;有网上的教程&#xff0c;也有视频直播课程。 很多办公人员用Excel这种表格软件与VBA结合&#xff0c;甚至用不遗余力去学习Python编程语法&#xff0c;但Exce…

2023年会计师事务所研究报告

第一章 行业发展概况 1.1 行业概况 会计师事务所是专门从事财务、税务等领域的专业服务机构&#xff0c;其服务范围涵盖了审计、会计、税务、咨询等多个方面。 近年来&#xff0c;随着全球经济的不断发展和国际贸易的增加&#xff0c;会计师事务所行业也得到了快速发展。据统…

G8期刊《全体育》期刊简介及投稿要求

G8期刊《全体育》期刊简介及投稿要求 《全体育》是由湖南体育产业集团有限公司主管、体坛传媒集团股份有限公司主办、中教体育 出版发行的体育综合性期刊。 主管&#xff1a;湖南体育产业集团有限公司 主办&#xff1a;体坛传媒集团股份有限公司 国内刊号&#xff1a;CN4…

「实战教程」如何使用POI读取模板PPT填充数据并拼接至目标文件

文章目录一、PPT文件格式介绍1、PPT文件格式的概述2、HSLF和XSLF的区别3、如何选择合适的POI类库二、SlideShow三、读取PPT文件1. 加载PPT文件2. 获取PPT文件中的幻灯片3. 获取幻灯片中的形状元素四、修改PPT文件内容1. 幻灯片操作1.1 新增幻灯片1.2 删除幻灯片1.3 移动幻灯片1…

MySQL中count(1)和count(*)哪个性能好?

当我们对某一张表中的数据需要统计数量的时候&#xff0c;我们通常会用到count(1)、count(*)或者count(字段)&#xff0c;而这三种哪个方式的count效率最高呢&#xff1f;先来说结论&#xff1a; count(1) count(*) > count(字段) 为什么会得到如上的结论&#xff0c;下面来…

xilinx FPGA FIFO IP核的使用(VHDLISE)

1.新建工程和ip核文件 下图显示了一个典型的写操作。拉高WR_EN&#xff0c;导致在WR_CLK的下一个上升边缘发生写入操作。因为FIFO未满&#xff0c;所以WR_ACK输出1&#xff0c;确认成功的写入操作。当只有一个附加的单词可以写入FIFO时&#xff0c;FIFO会拉高ALMOST_FULL标志。…

图数据结构与算法

什么是图数据的结构 图是由顶点和边组成的非线性数据结构。顶点有时也称为节点,边是连接图中任意两个节点的线或弧。更正式地说,图由一组顶点 ( V ) 和一组边 ( E ) 组成。该图由 G(E, V) 表示。 图的组成部分 顶点:顶点是图的基本单位。有时,顶点也称为顶点或节点。每个节…

私有化部署VideoTogether一起看视频

本文折腾始于 2022 年 9 月&#xff0c;但因为种种原因并未写完&#xff0c;最近&#xff0c;因为有朋友需要&#xff0c;又重新开始捡了起来&#xff0c;然而&#xff0c;我发现官方已经把私有化部署的相关文档删了&#xff0c;原因不得而知。 什么是 VideoTogether ? VideoT…

拥抱自动化测试,快速升职加薪丄Selenium+Pytest自动化测试框架教你如何做到

目录&#xff1a;导读 引言 SeleniumPytest自动化测试框架是目前最流行的自动化测试工具之一&#xff0c;其强大的功能和易用性援助许多开发人员和测试人员。 selenium自动化 pytest测试框架禅道实战 选用的测试网址为我电脑本地搭建的禅道 conftest.py更改 config.ini更…

【权限维持】域控后门SSPHOOKDSRMSID万能钥匙

文章目录内网域-权限维持-基于验证DLL加载-SSP方法一&#xff1a;但如果域控制器重启&#xff0c;被注入内存的伪造的SSP将会丢失。方法二&#xff1a;使用此方法即使系统重启&#xff0c;也不会影响到持久化的效果。使用总结内网域-权限维持-基于验证DLL加载-HOOK方法一&#…

esxi的安装配置以及新建虚拟机

esxi的安装配置以及新建虚拟机1_esxi的安装1.1_镜像下载1.2_启动盘制作1.3_安装教程1.3.1_进入Bios Manager选择使用U盘启动1.3.2_配置esxi&#xff08;主要是配置网络&#xff09;1.3.3_远程连接&#xff08;直接在电脑上输入ip地址登录即可&#xff09;2_新建虚拟机装操作系统…

没有他们,人工智能只能死翘翘

我过去写过一篇文章《很多所谓伟大的贡献&#xff0c;其实都是狗屎运》&#xff0c;今天我也写写人工智能。&#xff08;1&#xff09;人才深度神经网络如果不从明斯基和罗森布拉特说起&#xff0c;那就应该可以从1965年Ivakhnenko发明前馈神经网络说起。但关键里程碑是出自Rum…