【算法练习Day22】 组合总和组合总和 II分割回文串

news2024/10/5 20:24:00

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 组合总和
  • 组合总和 II
  • 分割回文串
    • 本题的难点
  • 总结:

组合总和

39. 组合总和 - 力扣(LeetCode)
在这里插入图片描述

题目要求是可以使用重复的数据进行构造答案,整体思路和组合总和3没差多少,就只有一点细节需要注意。幸运的是这道题给的是一个无重复数字的数组,那么有什么区别吗?肯定是有区别的,有重数组不管我们要的答案是可以一个数字取很多次,还是不可以,都要进行数组去重。打个比方,我们数组里有两个2,目标值是4,那么我们可以一个数字取多次的话,比如用第一个2返回一组答案是{2,2},那么再用第二个数字2时候,我们取到的组合不是和用第一个数字取到的是一样的吗?这肯定不行,虽然我们可以一个数字重复用,但是最后返回的答案不能有相同的。

说完了这一点,我们直接看代码,看看和上一道题都有哪些不同

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtacking(vector<int>&candidates,int target,int sum,int startIndex)
    {
        if(sum>target)
        {
            return;
        }
        if(sum==target)
        {
            result.push_back(path);
            return;
        }
        for(int i=startIndex;i<candidates.size();i++)
        {
            sum+=candidates[i];
            path.push_back(candidates[i]);
            backtacking(candidates,target,sum,i);
            sum-=candidates[i];
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        result.clear();
        path.clear();
        backtacking(candidates,target,0,0);
        return result;
    }
};

实际上不同之处并没有很多,只有每次递归传入的是i,而并非i+1,这是因为我们的数组中元素可以重复选取,所以我们下一次传进来的还是i,那么我们如何选到其他的数字呢,当第一个数字选完了,我们回溯回来了,进行i++也就到下一个数字的遍历了,这里的start的作用,同样是告诉for循环本次从哪个数开始选取。而剪枝部分,主要体现在sum>target上,我们当然也可以将它们写在for循环的判断部分,判断sum+nums[i]是否小于等于target这样的话我们才能够进入循环,否则不进入,其实和直接判断思路是一样的。

组合总和 II

40. 组合总和 II - 力扣(LeetCode)
在这里插入图片描述

组合总和2是我们组合回溯的最后一道例题了,它涉及到了去重的逻辑,注意这里只是数组中的单个的数据不能重复选,但是如果数组中给出了有相同的元素我们还是可以选择的它们只是数值上相等,但是所对应的下标不相等,这点很重要。去重的逻辑,我们需要画树型图来辅助理解,我们需要怎么样去重,首先我们应该将数组重新排序,重新排序的目的是让可能重复的数据挨在一起,方便我们去重。当上一个数字和我们本次要取的数字相等时候,可以取吗?答案是可以的,只要是不重复取一个位置就可以

那么什么时候需要去重?当上一个数字和本次要取的数字相等时并且上一个数字我们这个数组中并没有取,但是本次即将要取了,那么我们直接跳过这个数字,为什么呢?因为前面的数字如果和本次数据值相等,那么它们取到的组合是一模一样的,这就造成了答案上的重复,这是一定要避免的,我们可以设立一个数组来保存我们取过的数值,具体看代码

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtacking(vector<int>&candidates,int target,int sum,int startIndex,vector<bool>& used)
    {
        if(sum==target)
        {
            result.push_back(path);
            return;
        }
        for(int i=startIndex;i<candidates.size()&&sum+candidates[i]<=target;i++)
        {
            if(i>0&&candidates[i]==candidates[i-1]&&used[i-1]==false)
            {
                continue;
            }
            sum+=candidates[i];
            path.push_back(candidates[i]);
            used[i]=true;
            backtacking(candidates,target,sum,i+1,used);
            used[i]=false;
            sum-=candidates[i];
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<bool> used(candidates.size(),false);
        path.clear();
        result.clear();
        sort(candidates.begin(),candidates.end());
        backtacking(candidates,target,0,0,used);
        return result;
    }
};

这里的剪枝逻辑还是和上一题相同的,如果大于了直接跳出,不能再让他搜索到最后才跳出。如果能够理解用数组来标记原数组中的数据是否在本答案数组中被取,和理解为什么我们在遇到两个数挨着相等并且当上一个相等的数没有取这次又取得了我们直接跳出的逻辑,相信这道题还是和不成问题的,这相当于横向的一个答案去重,相等的数字答案组合一定相等的,所以我们才直接continue,让i++遍历其他的数字,但是我们不能够直接break,因为直接break的话我们就无法在本次遍历其他的数字了,遇到了和上一次一样的数字直接跳出来了,会影响后面的数字选出答案。

分割回文串

131. 分割回文串 - 力扣(LeetCode)
在这里插入图片描述

这是我们回溯算法专题的第一道分割问题,分割问题大多都是较难的,这道题其实也很难。给我们一个字符串,要求是返回它的所有分割方法,且这些分割方法分割出来的子串均为回文子串。

首先要知道怎么分割,可以画树形图来理解,例如分割aab这个字符串,可以先分割a,再分割a再分割b,或者先分割a再将ab做整体分割等等。知道了怎么分割我们再来想回溯函数的终止条件是什么?终止条件实际上是当前的分割线走到了要分割的该字符串的最后一个位置。这是和我们之前做的组合问题的终止条件不一样的地方,一样的是我们可以类比组合问题,这道题仍然需要一个start来标识下一次从哪里进行分割,因为已经被分割的字符串不能重复分割,所以我们要记录下一次分割的位置。那么代码实现,什么来表示分割线呢,就是start。怎么判断子串是否回文呢,这一点很好写,那怎么表示分割子串的区间呢?这一点需要想清楚,start代表分割子串的左区间,i也就是for循环里面的起始遍历位置i代表右区间,start和i不是相等的吗?确实是相等的,但是它们不可能一直相等,循环调整部分i会自增,但是start在本次循环内部不会自增,我们可以调整i来实现对于子串的范围圈定。

class Solution {
public:
    vector<vector<string>>result;
    vector<string>path;
    void backtraking(string s,int start)
    {
        if(start==s.size())
        {
            result.push_back(path);return;
        }
        for(int i=start;i<s.size();i++)
        {
            if(panduan(s,start,i))
            {
                string p=s.substr(start,i-start+1);
                path.push_back(p);
            }
            else continue;
            backtraking(s,i+1);
            path.pop_back();
        }
    }

    bool panduan(string s,int start,int i)
    {
        int left=start;int right=i;
        while(left<right)
        {
            if(s[left++]!=s[right--])return false;
        }
        return true;
    }
    vector<vector<string>> partition(string s) 
    {
        if(s.size()==0)return result;
        backtraking(s,0);
        return result;
    }
};

我们在for循环里判定,如果当前的子串不是回文的,那么我们continue直接让i++增大搜索区间。这里可能有一个疑问的点,那如果搜索的区间永远都是不回文的是不是就搜不到正确答案了,这点不用担心,单个字符就是回文的,所以它一定会往下搜索出一个答案出来。回文的判断代码,十分简单,就只是用双指针将传入的子串范围从前后一起遍历,如果有不等的字符直接return就可以了。

本题的难点

本题的难点在于:分割子串时候如何表示切割字符串的切割线,如何表示切割出来的子串的范围,以及如何写回溯算法中终止条件的代码,如果能够搞清楚,就可以做出这道题目了。

总结:

今天我们完成了组合总和、组合总和 II、分割回文串三道题,相关的思想需要多复习回顾。接下来,我们继续进行算法练习。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

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

相关文章

多继承vs查看类结构

多继承里面的虚函数 类A有两个虚函数&#xff0c;类B重写了其中一个&#xff0c;类C重写了两个&#xff1b; 类C里面可以重写所有继承到的虚函数&#xff08;类A、类B里面的虚函数&#xff09; class A { public:virtual void init() { std::cout << "A init !&qu…

uniapp collapse动态生成多个折叠面板手动展开收起(包括uni-ui版)

前言 官方文档没有暴露出相关api&#xff0c;那就看看组件源码。 以下示例均通过 vue-cli 创建的 uni-app h5 项目 uView&#xff08;1.x&#xff09;版本 源码 node_modules\uview-ui\components\u-collapse-item\u-collapse-item.vue 这个方法是用来改变折叠面板子组件收起还…

Jmeter接口测试 —— jmeter对图片验证码的处理

jmeter对图片验证码的处理 在web端的登录接口经常会有图片验证码的输入&#xff0c;而且每次登录时图片验证码都是随机的&#xff1b;当通过jmeter做接口登录的时候要对图片验证码进行识别出图片中的字段&#xff0c;然后再登录接口中使用&#xff1b; 通过jmeter对图片验证码…

亲,手撸图文博文太累了?试试这个神器!

这一篇博客有关如何使用[InternLM-XComposer]来写图文并茂的博文。InternLM-XComposer是一个基于人工智能的创作工具&#xff0c;它可以根据你的输入生成不同类型的内容&#xff0c;例如文章、诗歌、歌词、代码等。你可以使用它来创作有趣和有创意的博客&#xff0c;同时也可以…

【MySQL】数据库——表操作

文章目录 1. 创建表2. 查看表3. 修改表修改表名add ——增加modify——修改drop——删除修改列名称 4. 删除表 1. 创建表 语法&#xff1a; create table 表名字 ( 列名称 列类型 ) charset set 字符集 collate 校验规则 engine 存储引擎 ; charset set字符集 &#xff0c;若…

Unity SRP 管线【第二讲:Draw Call】

参考&#xff1a; https://edu.uwa4d.com/lesson-detail/282/1309/0?isPreview0 文章目录 参考&#xff1a;一、Shader1.HLSL引入2.获取Unity提供的标准输入3.Unity提供的运算库SpaceTransform库的宏对应补充&#xff1a; 4.标准库Common.hlsl5.SpaceTransforms库引入Commo…

Flutter视图原理之三棵树的建立过程

目录 三棵树的关系树的构建过程1.updateChild函数&#xff08;element的复用&#xff09;2.inflateWidget函数3.mount函数3.1 componentElement的实现3.2 RenderObjectElement的实现3.2.1 attachRenderObject函数 4.performRebuild函数 总结三棵树创建流程 三棵树的关系 Flutt…

【数组的使用续篇】

文章目录 以数组的形式打印数组打印方法&#xff1a;Arrays.toString(数组名) 数组排序大小排序方法是 Arrays.sort(数组名) 创建一个自己的打印数组的方法自己创建一个冒泡排序两数之间交换方法 逆置数组打印核心思路还是 i 和 j 交换 总结 以数组的形式打印数组 打印方法&am…

LeCun和Bengio“吵”起来了,人工智能是“潘多拉魔盒”吗?

作者 | 谢年年 上周末&#xff0c;深度学习领域最有影响力的三巨头之二Yann LeCun和Yoshua Bengio就AI的潜在风险和安全问题引发了一场激烈辩论&#xff0c;人工智能是“潘多拉魔盒”吗&#xff1f;这场辩论引来众多AI知名人士围观。 LeCun在Facebook上发起了这场辩论&#xff…

【Axure高保真原型】树筛选中继器表格

今天和大家分享树筛选中继器表格的原型模板&#xff0c;点的树节点的箭头可以展开或者收起子节点&#xff0c;点击节点内容&#xff0c;可以按照对应层级筛选右侧中继器表格的数据&#xff0c;那这个模板里的树和表格都是用中继器制作的&#xff0c;所以使用也很方便&#xff0…

从零开始学习秒杀项目

构思了很多种讲述这个简易版的秒杀项目的思路&#xff0c;比如按照功能分类&#xff0c;按照项目亮点串起来讲述&#xff0c;总觉得不适合基础薄弱的同学来学习&#xff0c;所以本项目按照从搭建开始&#xff0c;过程中需要什么来学习什么。 技术栈 SpringBootmybatisPlus&am…

【软考-中级】系统集成项目管理工程师 【16 变更管理】

持续更新。。。。。。。。。。。。。。。 【第十六章】变更管理 (选择2分 考点 1:变更的常见原因考点 2:变更管理的原则是项目基准化、变更管理过程规范化考点 3考点 4考点 5:变更的工作程序考点 6考点 7考点 8考点 9考点 10考点 11考点 12:变更分类系列文章经典语录 考点 1:变…

使用Python+selenium实现第一个自动化测试脚本

这篇文章主要介绍了使用Pythonselenium实现第一个自动化测试脚本&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值&#xff0c;需要的朋友们下面随着小编来一起学习学习吧 最近在学web自动化&#xff0c;记录一下学习过程。…

在Linux中,怎么查看自己电脑的系统架构是什么?

2023年10月18日&#xff0c;周三晚上 这些命令会返回一个字符串&#xff0c;表示系统的架构。 常见的架构包括 x86&#xff08;32位&#xff09;、x86_64&#xff08;64位&#xff09;、ARM 等。 方法1&#xff1a;使用uname命令 uname -m方法2&#xff1a;使用arch命令 ar…

现代 ERP 系统,如何使中小企业智能制造商受益?

中小企业智能制造商大多依靠手工操作或电子表格模式&#xff0c;或少数几个软件组成的集合体&#xff0c;或是依靠传统的ERP系统来管理企业运营。经营利润率低、订单到现金的周期缓慢、客户付款延迟、管理成本增加&#xff0c;使他们的生存变得更加困难。许多企业一直在以最少的…

uni-app通过 vuedraggable 创建上下拖动排序组件

我们右键项目 选择 使用命令行窗口打开所在目录 然后 在终端中输入 npm install vuedraggable --save导入 vuedraggable 然后组件编写代码如下 <template><view class"container"><draggable v-model"list" :options"dragOptions&…

自动化测试总计

最近要在新入职的公司准备一份自动化测试的培训&#xff0c;这是我在得知要做自动化测试培训以后&#xff0c;随手画了个图&#xff0c;压压惊&#xff1a; 这是我能想到的关于自动化测试的一些要点&#xff0c;然后根据一篇我三年前写的关于自动化测试的随笔更新了一下&#x…

网络安全内网渗透之信息收集--systeminfo查看电脑有无加域

systeminfo输出的内容很多&#xff0c;包括主机名、OS名称、OS版本、域信息、打的补丁程序等。 其中&#xff0c;查看电脑有无加域可以快速搜索&#xff1a; systeminfo|findstr "域:" 输出结果为WORKGROUP&#xff0c;可见该机器没有加域&#xff1a; systeminfo…

【NVIDIA】获取GPU利用率-cpp.md

在深度学习推理中&#xff0c;为了更加高效的利用 GPU&#xff0c;在多个推理任务实例中&#xff0c;创建新的实例以及分配到不同的 GPU 设备上&#xff0c;需要关注到当前 GPU 还有多少剩余&#xff0c;以便更好的分配 代码目录 . ├── CMakeLists.txt ├── src │ └─…