代码随想录算法训练营第二十六天 | 39. 组合总和,40.组合总和II, 131.分割回文串[回溯篇]

代码随想录算法训练营第二十六天

  • LeetCode 39. 组合总和
    • 题目描述
    • 思路
    • 参考代码
    • 总结
  • LeetCode 40.组合总和II
    • 题目描述
    • 思路
    • 参考代码
  • LeetCode 131.分割回文串
    • 题目描述
    • 思路
      • 切割问题
      • 回文判断
    • 参考代码
    • 总结


LeetCode 39. 组合总和

题目链接:39. 组合总和
文章讲解:代码随想录#39. 组合总和
视频讲解:带你学透回溯算法-组合总和(对应「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
输出: []

提示

  • 1 <= candidates.length <= 30
  • 2 <= candidates[i] <= 40
  • candidates 的所有元素 互不相同
  • 1 <= target <= 40

思路

同一个数字可以无限制重复使用,这和之前 77.组合 不太一样,所以每次递归遍历时,索引不需要+1。
target作为递归函数的终止条件。

也可以做一些剪枝的操作,比如前sum之和大于target时直接返回。

参考代码

/*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().*/int **res;
int cnt;
int sum;
typedef struct {int index;int nums[30];
}Data;
Data data = {0};void backtracking(int* candidates, int candidatesSize, int target, int** returnColumnSizes, int idx)
{if (sum == target) {res[cnt] = (int *)malloc(data.index * sizeof(int));for (int i = 0; i < data.index; i++) {res[cnt][i] = data.nums[i]; }(*returnColumnSizes)[cnt] = data.index;cnt++;return;}for (int i = idx; i < candidatesSize; i++) {if (sum + candidates[i] > target) continue; // 剪枝,跳过当前循环data.nums[data.index++] = candidates[i];sum += candidates[i];backtracking(candidates, candidatesSize, target, returnColumnSizes, i);sum -= candidates[i]; // 回溯data.index--;data.nums[data.index] = 0;}
}int** combinationSum(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes) {res = (int**)malloc(1000 * sizeof(int));*returnColumnSizes = (int*)malloc(sizeof(int) * 200);cnt = 0;sum = 0;backtracking(candidates, candidatesSize, target, returnColumnSizes, 0);*returnSize = cnt;return res;
}

总结

  1. 对于返回值以及returnColumnSizes的初始化时,空间大小不好选择,我每次都是试出来了,这个不太好。

LeetCode 40.组合总和II

题目链接:40.组合总和II
文章讲解:代码随想录#40.组合总和II
视频讲解:回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| 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]
]

提示

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

思路

需要注意几个点如下:

  • candidates 数组中的每个数字在每个组合中只能使用一次。
  • candidates 数组中的元素会有重复的。

这道题我们需要考虑去重的情况了。
所谓去重,其实就是使用过的元素不能重复使用。
那应该如何去重呢?
①首先对candidates 数组进行从小到大的排序,相同的数值的元素就连在一起了。
②构造一个与candidates 数组大小相同的used数组,用来表示元素是否使用过。
具体思路可以查看代码随想录。

我盗用两张图说明一下重复的情况。
在这里插入图片描述
在这里插入图片描述
在candidates[i] == candidates[i - 1]相同的情况下:

  • used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
  • used[i - 1] == false,说明同一树层candidates[i - 1]使用过

参考代码

int cnt;
int sum;
int* used;
int** ret;
typedef struct {int index;int nums[100];
} Data;
Data data = {0};int cmp(const void* p1, const void* p2) { return *(int*)p1 - *(int*)p2; }void backtracking(int* candidates, int candidatesSize, int target, int** returnColumnSizes, int idx) {if (sum == target) {ret[cnt] = malloc(sizeof(int) * data.index);for (int i = 0; i < data.index; i++)ret[cnt][i] = data.nums[i];(*returnColumnSizes)[cnt] = data.index;cnt++;return;}for (int i = idx; i < candidatesSize; i++) {if (sum + candidates[i] > target) // 剪枝操作break;// 当前执行到i,如果used[i - 1] == 0,说明candidates[i - 1]已经使用过了,直接跳过// 如果看不懂,可以多看看随想录的思路,然后自已在本地推导几遍if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == 0) continue;sum += candidates[i];data.nums[data.index++] = candidates[i];used[i] = 1;// 必须是i+1,下一层的循环跳过当前层的元素,指向下一个元素backtracking(candidates, candidatesSize, target, returnColumnSizes, i + 1);sum -= candidates[i]; // 回溯data.index--;data.nums[data.index] = 0;used[i] = 0;}
}int** combinationSum2(int* candidates, int candidatesSize, int target,int* returnSize, int** returnColumnSizes) {ret = (int**)malloc(10000 * sizeof(int*));used = (int*)malloc(100 * sizeof(int));*returnColumnSizes = (int*)malloc(sizeof(int) * 100);for (int i = 0; i < 100; i++) // 清空used数组used[i] = 0;cnt = 0;sum = 0;// 排序,将相同值的元素挨在一起qsort(candidates, candidatesSize, sizeof(int), cmp);backtracking(candidates, candidatesSize, target, returnColumnSizes, 0);*returnSize = cnt;return ret;
}

LeetCode 131.分割回文串

题目链接:[131.分割回文串 (https://leetcode.cn/problems/palindrome-partitioning/)
文章讲解:代码随想录#131.分割回文串
视频讲解:带你学透回溯算法-分割回文串(对应力扣题目:131.分割回文串)| 回溯法精讲!

题目描述

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

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

示例1

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

示例2

输入:s = “a”
输出:[[“a”]]

提示

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成

思路

看完题目描述后没有一点儿思路,还是得看一遍视频。
本题有两个关键点:
①字符串切割,可以使用回溯法进行不同方式的切割。
②对切割好的子串进行回文判断,如果是回文,则添加到返回的变量中。

切割问题

其实切割问题,可以采用回溯法进行切割,终止条件就是切割到了字符串的最后一个字符。
递归函数的返回值为void,参数有两个,一个是原字符串,另一个当前层遍历的起始位置idx。

在单层搜索的逻辑中会有一个for循环,相当于对树进行横向遍历,i的起始值为idx,i的终止值为strlen(s)。
首先对以idx/i为起始的字符串进行处理(第一层),
如果[idx, i]的子串为回文,则将子串添加到res变量中,
调用递归函数,对以i+1为起始的字符串进行处理(第二层)。。。
递归函数处理完后,进行回溯操作,然后对i+1继续下一次遍历。
如果不是回文,在同一层i+1继续遍历。

借用一张图说明一下树状关系:
在这里插入图片描述

回文判断

可以使用双指针法,一个从头向尾,一个从尾向前开始遍历,如果前后指针指向的元素相等,则说明是回文字符串。

参考代码

char*** partition(char* s, int* returnSize, int** returnColumnSizes) {// 待实现
}

总结

  1. 这道题的复杂之处就是要对收集的结果赋值给一个三维指针,时间有限,我暂时还没有想清楚,后面补上。

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

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

相关文章

【深度学习目标检测】十九、基于深度学习的芒果计数分割系统-含数据集、GUI和源码(python,yolov8)

使用深度学习算法检测芒果具有显著的优势和应用价值。以下是几个主要原因&#xff1a; 特征学习的能力&#xff1a;深度学习&#xff0c;特别是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;能够从大量的芒果图像中自动学习和提取特征。这些特征可能是传统方法难以手动…

如何在三维地球加载SQL Server、MySql、PostgreSQL的矢量数据?

通过以下方法可以将数据库SQL Server、MySql、PostgreSQL的矢量数据叠加到三维地球上。 方法/步骤 下载三维地图浏览器 http://www.geosaas.com/download/map3dbrowser.exe&#xff0c;安装完成后桌面上出现”三维地图浏览器“图标。 2、双击桌面图标打开”三维地图浏览器“…

2.25 day5 QT

闹钟 .h代码 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent> #include <QTime> #include <QTextToSpeech>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJ…

2024年 前端JavaScript入门到精通 第五天 笔记

5.1 -什么是对象以及基本使用 5.2-对象的操作-增删改 5.3-对象的操作-查的两种方法 5.4-对象的方法 5.5-遍历对象 5.6-渲染学生信息表案例 5.7-数学内置对象 Math - JavaScript | MDN 5.8-随机数函数 5.9-随机点名案例 5.10-猜数字游戏 5.11-随机颜色案例 <script>// 1. …

海豚调度DolphinScheduler入门学习

DS简介&#xff1a; DolphinScheduler 是一款分布式的、易扩展的、高可用的数据处理平台&#xff0c;主要包含调度中心、元数据管理、任务编排、任务调度、任务执行和告警等模块。其技术架构基于 Spring Boot 和 Spring Cloud 技术栈&#xff0c;采用了分布式锁、分布式任务队列…

你要不要搞副业

最近看到了几个网友关于年轻人要不要搞副业的一点讨论&#xff0c;学习到了很多。整理分享如下&#xff1a; plantegg 你要不要搞副业&#xff1f; 最近网上看到很多讨论搞副业和远程工作的&#xff0c;我也说点自己的经验看法 当然这完全是出于个人认知肯定不是完全对的、也…

[python pip] A new release of pip is available: 23.2.1 -> 24.0

翻译之后&#xff1a;〔通知〕新版本的pip可用&#xff1a;23.2.1->24.0 就是说&#xff0c;你的pip版本需要从当前的 23.2.1 升级到最新版本 24.0&#xff0c;执行如下命令&#xff1a; cmd命令以管理员身份进入目录 ${Python}\Python3.12.1\Scripts下&#xff0c;执行 p…

mysql group by分组后查询无数据补0

mysql经常会用到Group By来进行分组查询&#xff0c;但也经常会遇到一个问题&#xff0c;就是不满足条件的数据就不会显示,如图总共有五个业务,业务状态为3的就不会显示: 因此&#xff0c;想要实现&#xff0c;即使没有数据&#xff0c;也想让count显示出0而不是空的效果&…

数据结构2月25日

第一道&#xff1a; 第二道&#xff1a; 1、插入到prev和next中间 1.new(struct list_head*)malloc(sizeof(struct list_head*)); if(newNULL) { printf("失败\n"); return; } new->nextprev->next; prev->nextnew; return; 2、删除prve和next…

3.WEB渗透测试-前置基础知识-快速搭建渗透环境(上)

上一个内容&#xff1a;2.WEB渗透测试-前置基础知识-web基础知识和操作系统-CSDN博客 1.安装虚拟机系统 linux Kali官网下载地址&#xff1a; https://www.kali.org/get-kali/#kali-bare-metal Centos官网下载地址&#xff1a; https://www.centos.org/download/ Deepin官网下…

Sora 横空出世!国内一批创新公司要挂了吗?

2月16日凌晨&#xff0c;OpenAI 发布了自己的首个AI视频生成模型—Sora&#xff0c;这是一个历史性的里程碑&#xff0c;扩散模型结合OpenAI大获成功的transformer&#xff0c;在视觉领域实现了与大语言模型类似的突破。毫无疑问&#xff0c;视觉生成领域将有一次大的技术和商业…

一种基于道路分类特性的超快速车道检测算法

摘要&#xff1a; 本文介绍了一种新颖、简单但有效的车道检测公式。 车道检测是自动驾驶和高级驾驶员辅助系统 (ADAS) 的基本组成部分&#xff0c;在实际高阶驾驶辅助应用中&#xff0c;考虑车道保持、转向、限速等相关的控制问题&#xff0c;这种方式通常是通过受限的车辆计算…

《真象还原》读书笔记——第七章 中断处理

7.1 中断是什么&#xff0c;为什么中断 中断可以并发执行多个程序&#xff0c;提升系统利用率。 并发是单位时间内的积累工作量并行是真正同时进行的工作量 有了中断&#xff0c;我们才能一边使用键盘一边使用鼠标。 7.2 操作系统是中断驱动的 是操作系统是被动工作的&…

linux之前后端项目部署与发布

目录 前言 简介 一、安装Nginx 二、后端部署 2.1多个tomcat负载均衡 2.2 负载均衡 2.3 后端项目部署 三、前端部署 1.解压前端 2.Nginx配置文件修改 3.IP域名映射 4.重启Nginx服务 前言 上篇博主已经讲解过了单机项目的部署linux之JAVA环境配置JDK&Tomcat&a…

KDD 2023 图神经网络方向论文总结

ACM SIGKDD&#xff08;国际数据挖掘与知识发现大会&#xff0c;KDD&#xff09;是数据挖掘领域历史最悠久、规模最大的国际顶级学术会议&#xff0c;也是首个引入大数据、数据科学、预测分析、众包等概念的会议。今年&#xff0c;第29届 KDD 大会在美国加州长滩举行&#xff0…

YOLO如何训练自己的模型

目录 步骤 一、打标签 二、数据集 三、跑train代码出模型 四、跑detect代码出结果 五、详细操作 步骤 一、打标签 &#xff08;1&#xff09;在终端 pip install labelimg &#xff08;2&#xff09;在终端输入labelimg打开 如何打标签&#xff1a; 推荐文章&#xf…

【初始RabbitMQ】延迟队列的实现

延迟队列概念 延迟队列中的元素是希望在指定时间到了之后或之前取出和处理消息&#xff0c;并且队列内部是有序的。简单来说&#xff0c;延时队列就是用来存放需要在指定时间被处理的元素的队列 延迟队列使用场景 延迟队列经常使用的场景有以下几点&#xff1a; 订单在十分…

蓝桥杯备战刷题(自用)

1.被污染的支票 #include <iostream> #include <vector> #include <map> #include <algorithm> using namespace std; int main() {int n;cin>>n;vector<int>L;map<int,int>mp;bool ok0;int num;for(int i1;i<n;i){cin>>nu…

Redis实现滑动窗口限流

常见限流算法 固定窗口算法 在固定的时间窗口下进行计数&#xff0c;达到阈值就拒绝请求。固定窗口如果在窗口开始就打满阈值&#xff0c;窗口后半部分进入的请求都会拒绝。 滑动窗口算法 在固定窗口的基础上&#xff0c;窗口会随着时间向前推移&#xff0c;可以在时间内平滑控…

HUAWEI Programming Contest 2024(AtCoder Beginner Contest 342)

D - Square Pair 题目大意 给一长为的数组&#xff0c;问有多少对&#xff0c;两者相乘为非负整数完全平方数 解题思路 一个数除以其能整除的最大的完全平方数&#xff0c;看前面有多少个与其余数相同的数&#xff0c;两者乘积满足条件&#xff08;已经是完全平方数的部分无…