代码随想录第二十四天 39.组合总和 40.组合总和II 131.分割回文串

LeetCode 39 组合总和

题目描述

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例 1:

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

示例 2:

输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]

示例 3:

输入: candidates = [2], target = 1
输出: []

思路

这一题思路不同的地方首先在于终止条件,这里的终止条件不只有在总和等于目标和的时候终止,还有在sum大于目标总和的时候,也需要终止,否则会进入无限循环。

另一点不同的地方在于这次的数字可以重复取,startindex控制的是循环的起始位置,这里循环的起始位置是在改变的,但是递归的时候,传入backtracking函数的i是用来控制第三层子树取哪些值的,所以这时候传入的值从i+1变为i。

代码实现

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

LeetCode 40 组合总和II 

题目描述

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。 

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

思路

  • 递归函数参数

与39题套路相同,此题还需要加一个bool型数组used,用来记录同一树枝上的元素是否使用过。

这个集合去重的重任就是used来完成的。

代码如下:

vector<vector<int>> result; // 存放组合集合
vector<int> path;           // 符合条件的组合
void backtracking(vector<int>& candidates, int target, int sum, int startIndex, vector<bool>& used) {
  • 递归终止条件

这一题的终止条件和上一题一样,这里的终止条件不只有在总和等于目标和的时候终止,还有在sum大于目标总和的时候,也需要终止,否则会进入无限循环。

代码如下:

if (sum > target) { // 这个条件其实可以省略
    return;
}
if (sum == target) {
    result.push_back(path);
    return;
}
  • 单层搜索的逻辑

这里我们需要去重的地方是如果数组第一个数与第二个数相同,那么第二个数的分支就全部不需要再读取,因为第一个数的分支一定会包含第二个子树的所有分支。而我们使用used数组的目的是不可以忽略组合中有相同的数字的情况,因为如果剪枝条件只有candidates[i] == candidates[i - 1],那么就会将[1 1 2]这样的组合忽略掉,所以我们需要用used数组去判断,在used[i - 1] == false的情况下,我们才可以确定组合中没有重复数字。

40.组合总和II1

代码实现

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

 LeetCode 131 分割回文串

题目描述

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

回文串 是正着读和反着读都一样的字符串。

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

输入:s = "a"
输出:[["a"]]

思路

  • 递归函数参数

全局变量数组path存放切割后回文的子串,二维数组result存放结果集。 (这两个参数可以放到函数参数里)

本题递归函数参数还需要startIndex,因为切割过的地方,不能重复切割,和组合问题也是保持一致的。

代码如下:

vector<vector<string>> result;
vector<string> path; // 放已经回文的子串
void backtracking (const string& s, int startIndex) {
  • 递归函数终止条件

131.分割回文串

从树形结构的图中可以看出:切割线切到了字符串最后面,说明找到了一种切割方法,此时就是本层递归的终止条件。

那么在代码里什么是切割线呢?

在处理组合问题的时候,递归参数需要传入startIndex,表示下一轮递归遍历的起始位置,这个startIndex就是切割线。

所以终止条件代码如下:

void backtracking (const string& s, int startIndex) {
    // 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
    if (startIndex >= s.size()) {
        result.push_back(path);
        return;
    }
}
  • 单层搜索的逻辑

来看看在递归循环中如何截取子串呢?

for (int i = startIndex; i < s.size(); i++)循环中,我们 定义了起始位置startIndex,那么 [startIndex, i] 就是要截取的子串。

首先判断这个子串是不是回文,如果是回文,就加入在vector<string> path中,path用来记录切割过的回文子串。

代码如下:

for (int i = startIndex; i < s.size(); i++) {
    if (isPalindrome(s, startIndex, i)) { // 是回文子串
        // 获取[startIndex,i]在s中的子串
        string str = s.substr(startIndex, i - startIndex + 1);
        path.push_back(str);
    } else {                // 如果不是则直接跳过
        continue;
    }
    backtracking(s, i + 1); // 寻找i+1为起始位置的子串
    path.pop_back();        // 回溯过程,弹出本次已经添加的子串
}

注意切割过的位置,不能重复切割,所以,backtracking(s, i + 1); 传入下一层的起始位置为i + 1

代码实现

class Solution {
public:
    vector<string> path;
    vector<vector<string>> result;
    void backtracking(string& s,int startindex){
        if(startindex >= s.size()){
            result.push_back(path);
            return;
        }
        for(int i = startindex;i < s.size();i++){
            if(isPalindrome(s,startindex,i)){
                path.push_back(s.substr(startindex,i - startindex + 1));
            }
            else{
                continue;
            }
            backtracking(s,i + 1);
            path.pop_back();
        }
    }
    bool isPalindrome(string s,int start,int end){
        for(int i = start,j = end;i < j;i++,j--){
            if(s[i] != s[j]){
                return false;
            }
        }
        return true;
    }
    vector<vector<string>> partition(string s) {
        backtracking(s,0);
        return result;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电表(3)EC600N 4G模块通过mqtt向服务器发送数据

工具 1、ec600 2、stm32f030c8 3、keil5 4、腾讯云服务器&#xff08;ubutu20.04&#xff09; mqtt服务器 sudo apt install mosquitto mosquitto-clients sudo systemctl start mosquitto sudo vim /etc/mosquitto/mosquitto.conf sudo systemctl status mosquittolistene…

Aspose.Words For JAVA 动态制作多维度表格(涵2024最新无水印包)

全网最全Aspose.Words For JAVA 高级使用教程: CSDNhttps://blog.csdn.net/LiHaoHang6/article/details/133989664?spm1001.2014.3001.5501 运行截图&#xff1a; 所谓多维度表格通常包含多个维度, 每个维度都代表一种数据属性,多维度表格可以用于数据分析&#xff0c;通过不…

ArcgisForJS如何使用ArcGIS Server发布的切片地图服务?

文章目录 0.引言1.准备海量地理数据2.ArcGIS Server发布切片地图服务3.ArcgisForJS使用ArcGIS Server发布的切片地图服务 0.引言 ArcGIS Server是一个由Esri开发的地理信息系统&#xff08;GIS&#xff09;服务器软件&#xff0c;它提供了许多功能&#xff0c;包括发布切片地图…

Python实战:统计字符串中的英文字母、空格、数字及其他字符出现的个数

Python实战&#xff1a;统计字符串中的英文字母、空格、数字及其他字符出现的个数 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程 &…

Servlet使用过程中常见问题总结

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;Servlet使用过程中常见问题总结 前言:笔者在学习Servlet的过程中遇到了很多问题,这里总结一下 1.乱码问题 如果我们在响应报文中传输中文"你好",那么在浏览器之中显示…

Redis中的AOF重写到底是怎么一回事

首先我们知道AOF和RDB都是Redis持久化的方法。RDB是Redis DB&#xff0c;一种二进制数据格式&#xff0c;这样就是相当于全量保存数据快照了。AOF则是保存命令&#xff0c;然后恢复的时候重放命令。 AOF随着时间推移&#xff0c;会越来越大&#xff0c;因为不断往里追加命令。…

Java基于SpringBoot+Vue的图书馆管理系统,附源码,数据库

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

一款跳转警告HTML单页模板源码

一款跳转警告HTML单页模板,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 代码如下 <!DOCTYPE html> <html> <!--QQ沐编程 www.q…

HarmonyOS—使用预览器查看应用/服务效果

DevEco Studio为开发者提供了UI界面预览功能&#xff0c;可以查看应用/服务的UI界面效果&#xff0c;方便开发者随时调整界面UI布局。预览器支持布局代码的实时预览&#xff0c;只需要将开发的源代码进行保存&#xff0c;就可以通过预览器实时查看应用/服务运行效果&#xff0c…

统计图玫瑰图绘制方法

统计图玫瑰图绘制方法 常用的统计图有条形图、柱形图、折线图、曲线图、饼图、环形图、扇形图。 前几类图比较容易绘制&#xff0c;饼图环形图绘制较难。 还有一种玫瑰图的绘制也较难&#xff0c;今提供玫瑰图的绘制方法供参考。 本方法采用C语言的最基本功能&#xff1a; &am…

axure9.0 工具使用思考

原型设计软件【AxureRP】快速原型设计工具原型设计软件【AxureRP】快速原型设计工具原型设计软件【AxureRP】快速原型设计工具原型设计软件【AxureRP】快速原型设计工具原型设计软件【AxureRP】快速原型设计工具原型设计软件【AxureRP】快速原型设计工具原型设计软件【AxureRP】…

Kafka3.x进阶

来源&#xff1a;B站 目录 Kafka生产者生产经验——生产者如何提高吞吐量生产经验——数据可靠性生产经验——数据去重数据传递语义幂等性生产者事务 生产经验——数据有序生产经验——数据乱序 Kafka BrokerKafka Broker 工作流程Zookeeper 存储的 Kafka 信息Kafka Broker 总…

预告 | 飞凌嵌入式即将亮相第八届瑞芯微开发者大会(RKDC2024)

2024年3月7~8日&#xff0c;第八届瑞芯微开发者大会&#xff08;RKDC2024&#xff09;将在福州举办&#xff0c;本届大会以“AI芯片AI应用AloT”为主题&#xff0c;邀请各行业的开发者共启数智化未来。 本届大会亮点颇多&#xff0c;不仅有13大芯片应用展示、9场产品和技术论坛…

洛谷 【算法1-2】排序

【算法1-2】排序 - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 鄙人不才&#xff0c;刷洛谷&#xff0c;迎蓝桥&#xff0c;【算法1-2】排序 已刷&#xff0c;现将 AC 代码献上&#xff0c;望有助于各位 P1271 选举学生会 【深基9.例1】选举学生会 - 洛谷 题目 解答…

YOLOv9 | 利用YOLOv9训练自己的数据集 -> 推理、验证(源码解读 + 手撕结构图)

一、本文介绍 本文给大家带来的是全新的SOTA模型YOLOv9的基础使用教程&#xff0c;需要注意的是YOLOv9发布时间为2024年2月21日&#xff0c;截至最近的日期也没有过去几天&#xff0c;从其实验结果上来看&#xff0c;其效果无论是精度和参数量都要大于过去的一些实时检测模型&…

智能水浸传感器拆解指导,水浸传感器有哪些种类?

很多朋友听说过智能水浸传感器&#xff0c;当我们的厨房或者卫生间发生漏水&#xff0c;只要提前安装放置好一个水浸传感器&#xff0c;哪怕我们身处外地也能发现并及时处理。除此之外&#xff0c;数据中心、机房、仓库、实验室、工厂、档案馆等也是智能水浸传感器的常见应用场…

如何图片无损放大?分享两个无损放大方法

在数字化时代的洪流中&#xff0c;我们时常被细微之处的美丽所打动——那些精致的画面&#xff0c;那些清晰的细节。然而&#xff0c;随着图片的放大&#xff0c;我们常常面临一个难题&#xff1a;清晰度的损失。此时&#xff0c;图片无损放大软件能够在不损失图片质量的前提下…

宝塔面板安装了mysql5.7和phpMyadmin,但是访问phpMyadmin时提示502 Bad Gateway

操作流程截图如下&#xff1a; 原因是没有选择php版本 选择php版本 下一页找到phpMyAdmin&#xff0c;选择设置 目前只有纯净态&#xff0c;说明没有php环境&#xff0c;前去安装php环境 点击安装&#xff0c;选择版本&#xff0c;这里选择的是7.4版本&#xff0c;编译安…

设计模式六:策略模式

1、策略模式 策略模式定义了一系列的算法&#xff0c;并将每一个算法封装起来&#xff0c;使每个算法可以相互替代&#xff0c;使算法本身和使用算法的客户端分割开来&#xff0c;相互独立。 策略模式的角色&#xff1a; 策略接口角色IStrategy&#xff1a;用来约束一系列具体…

抖音爬虫批量视频提取功能介绍|抖音评论提取工具

抖音爬虫是指通过编程技术从抖音平台上获取视频数据的程序。在进行抖音爬虫时&#xff0c;需要注意遵守相关法律法规和平台规定&#xff0c;以确保数据的合法获取和使用。 一般来说&#xff0c;抖音爬虫可以实现以下功能之一&#xff1a;批量视频提取。这个功能可以用于自动化地…