Leetcoder Day23| 回溯part03:组合+分割

语言:Java/Go

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 。仅有这两种组合。

提示:

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

本题的一大特点是没有组合数量的要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。这里的剪枝操作就是,如果当前的sum已经大于target。

class Solution {List<List<Integer>> res= new ArrayList<>();LinkedList<Integer> path =new LinkedList<>();public void backTracking(int[] candidates, int target, int sum, int startIdx){if(sum == target){res.add(new ArrayList<>(path));return;}if(sum > target) return;for(int i = startIdx; i < candidates.length; i++){sum += candidates[i];path.add(candidates[i]);if (sum <= target) {backTracking(candidates, target, sum, i);  //注意这里传递的是 i,而不是i+1,为了可以重复取值}sum -= candidates[i];path.removeLast();}}public List<List<Integer>> combinationSum(int[] candidates, int target) {backTracking(candidates, target, 0, 0);return res;}
}
  • 组合没有数量要求
  • 元素可无限重复选取

组合总结

1. 什么时候需要startIdx:如果是一个集合来求组合,就需要,如果是多个集合取组合,就不需要。

2. 什么时候在调用递归backTracking ()的时候+1:如果不可以重复,则需要+1,否则不用+1

40.组合总和II

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

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

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

  • 示例 1:
  • 输入: candidates = [10,1,2,7,6,1,5], target = 8,
  • 所求解集为:
[[1, 7],[1, 2, 5],[2, 6],[1, 1, 6]
]
  • 示例 2:
  • 输入: candidates = [2,5,2,1,2], target = 5,
  • 所求解集为:
[[1,2,2],[5]
]

本题和上一题的区别在于:

  1. 本题candidates中的每个数字在每个组合中只能使用一次。
  2. 本题数组candidates的元素是有重复的,而上一题是无重复元素的数组candidates

关于使用一次这个问题的理解:组合问题可以抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过。示例中给出的组合,在同一个组合中可以有重复,但是不能有重复的组合。

同一树枝上的都是一个组合里的元素,不用去重。同一树层上的是不同的组合,所以不可以重复。具体来讲,假如数组为[1,1,2,7],那么如果第一个1取完以后,继续从剩下的两个元素中取值会出现[1,1],[1,2],[1,7]这个操作是可以的,因为前两个1只是数值相同但并不是同一个元素,但是如果第一次取的是第二个1,那么其实后面的取值过程会和取第一个1的时候重复,这就造成了树层的重复。所以去重的方法就是,将当前的candidates数组排序以后,如果candidates[i]=candidates[i-1] 就跳过当前循环,继续寻找下一个数。

其实可以不借助新的数组,用startIdx进行去重也可以。

import java.util.Arrays;
class Solution {List<List<Integer>> res=new ArrayList<>();LinkedList<Integer> path =new LinkedList<>();public void backTracking(int[] candidates, int target, int sum, int startIdx){if(sum>target) return;if(sum == target){res.add(new ArrayList<>(path));}for(int i=startIdx;i<candidates.length;i++){// 要对同一树层使用过的元素进行跳过if(i>startIdx && candidates[i]==candidates[i-1]){continue;}sum+=candidates[i];path.add(candidates[i]);if(sum<=target){backTracking(candidates, target, sum,i+1);}sum-=candidates[i];path.removeLast();}}public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);backTracking(candidates, target, 0,0);return res;}
}

131.分割回文串

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

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

示例: 输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ]

这道题需要解决两个问题:(1)如何切割(2)怎么判断是否为回文串

切割问题其实类似于组合问题,也可以抽象为一个树结构

这里切割过的地方,不能重复切割,和组合问题也是保持一致的,所以也需要startIdx。

从图中可以看到,切割线切到了字符串最后面,说明找到了一种切割方法,此时就是本层递归的终止条件。每次切割是从startIdx开始的,所以startIdx即为切割线。当startIdx>=s.length()时,切割终止。

每切割一次,就要判断剩下的子串是否为回文串,如果是回文串,就将其加入path中。如果不是,就跳过。

可以用双指针法判断是否为回文串,设置start和end指针,如果前后指针所指向的元素相等,直到start==end,那么就是回文串。

class Solution {List<List<String>> res=new ArrayList<>();LinkedList<String> path = new LinkedList();public boolean isPalindrome(String s, int start, int end){for(int i=start, j=end;i<j;i++,j--){if(s.charAt(i)!=s.charAt(j)){return false;}}return true;}public void backTracking(String s, int startIdx){if(startIdx>=s.length()){res.add(new ArrayList<>(path));}for(int i=startIdx;i<s.length();i++){if(isPalindrome(s, startIdx, i)){String str=s.substring(startIdx, i+1);path.add(str);}else{continue;}backTracking(s, i+1); //确保不重复path.removeLast();}}public List<List<String>> partition(String s) {backTracking(s,0);return res;}
} 

本题难点和思路如下:

  • 切割问题可以抽象为组合问题
  • 如何模拟那些切割线
  • 切割问题中递归如何终止
  • 在递归循环中如何截取子串
  • 如何判断回文

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

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

相关文章

机器学习是什么

机器学习是什么 引言 机器学习&#xff08;Machine Learning&#xff0c;简称ML&#xff09;是人工智能&#xff08;AI&#xff09;领域中的重要分支&#xff0c;旨在通过让计算机系统自动学习和适应&#xff0c;不需要明确的编程指导。机器学习的发展为我们提供了一种新的方…

环形光源让图像质量瞬间提升,一探究竟吧!

光源对机器视觉检测系统的性能起着重要作用,精确的光学结构设计可以提高捕获图像的质量,准确地分离目标和背景信息,不充足的光线会使捕捉到的图像无法满足需求&#xff0c;针对不同的检测对象,不同的形状光源应运而生。我们来看看最常用的LED光源之一—环形光源。 环形光源&…

代码随想录算法训练营day41 | 01背包问题 二维、01背包问题 一维、416. 分割等和子集

背包问题的理论基础重中之重是01背包 01背包问题 二维 二维dp的01背包 确定dp数组以及下标的含义&#xff1a;dp[i][j]表示从下标为[0-i]的物品里任意取&#xff0c;放进容量为j的背包&#xff0c;价值总和最大是多少确定递推公式&#xff1a;dp[i][j] max(dp[i - 1][j], d…

vue3 使用pina

一、Vue 3 项目中集成Pina 状态管理库 要在 Vue 3 项目中使用 Pina&#xff08;Vue 3 状态管理库&#xff09;&#xff0c;您可以按照以下步骤操作&#xff1a; 1. 安装 Pina 库相应的插件&#xff1a; yarn add pinia # 或者使用 npm npm install pinia 2. 在您的 Vue 3 项…

电脑休眠之后唤不醒

现象&#xff1a;午休时间电脑休眠了&#xff0c;醒来之后发现在密码输入界面&#xff0c;但鼠标键盘没反应。按重启键或电源机重新开机&#xff0c;结果开不了机。 原因&#xff1a;1、内存条脏了&#xff0c;导致内存条读取失败 2、休眠的时候硬盘休眠了&#xff0c;导致按…

如何在 CentOS 中配置 SSH 服务的 TCP 端口转发

在 CentOS 系统中&#xff0c;SSH&#xff08;Secure Shell&#xff09;服务提供了强大的功能&#xff0c;其中之一就是 TCP 端口转发。通过此功能&#xff0c;我们可以安全地将本地或远程服务器上的端口流量转发到其他主机上。本文将引导您如何在 CentOS 中启用或禁用 SSH 的 …

AngularJS安装版本问题

一、安装 Angular CLI 脚手架安装命令&#xff1a; npm install -g angular/cli 在安装前请确保自己安装NodeJS环境版本为V18及以上&#xff0c;否则会因node版本问题导致项目无法正常运行。 脚手架安装后&#xff0c;已提示了当前node版本必须为18.13.0或大于20.9.0版本&…

git之分支管理

一.理解分支 我们看下面这张图片&#xff1a; 在版本回退⾥&#xff0c;你已经知道&#xff0c;每次提交&#xff0c;Git都把它们串成⼀条时间线&#xff0c;这条时间线就可以理解为是⼀个分⽀。截⽌到⽬前&#xff0c;只有⼀条时间线&#xff0c;在Git⾥&#xff0c;这个分⽀…

javaScript打印n以内的素数——试除法及优化

素数&#xff1a;只能被1和它本身整除 试除法 试除法的时间复杂度为O(n*sqrt(n))&#xff0c;空间复杂度为O(1)&#xff0c;这已经是一种比较高效的解决方案了。 n如果不是质数&#xff0c;那么能整除的数一定与根号n。基于此缩小循环比较范围&#xff0c;并且一旦找到可以整除…

数字签名在游戏里的应用

数字签名是一种电子形式的签名,用于验证数字文档、消息或交易的真实性和完整性。它是基于公钥加密技术,通过使用发送者的私钥来签名文档,然后使用发送者的公钥验证签名的正确性。数字签名不仅能证明信息没有被篡改,也能证明信息的发送者是真实的,因此在很多安全敏感的应用…

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

4.1 函数的基本使用以及封装练习 ★ 函数命名规范 4.2 函数的参数以及默认参数 函数的灵魂&#xff01;&#xff01;&#xff01; 4.3 函数封装数组求和案例 4.4 函数返回值return 4.5 函数返回值细节以及上午总结 4.6 函数返回值案例-求最大值和最 4.7 函数复习以及断点进入函…

如何在Linux搭建MinIO服务并实现无公网ip远程访问内网管理界面

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器&#xff0c;可以在各种环境中运行&#xff0c;例如本地、Docker容器、Kubernetes集群等。它兼…

挑战杯 基于机器视觉的12306验证码识别

文章目录 0 简介1 数据收集2 识别过程3 网络构建4 数据读取5 模型训练6 加入Dropout层7 数据增强8 迁移学习9 结果9 最后 0 简介 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器视觉的12306验证码识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向…

springboot创建一个简单的web项目

要创建一个简单的Spring Boot Web项目&#xff0c;您可以按照以下步骤进行操作&#xff1a; 首先&#xff0c;您需要安装Java开发环境。确保您已经安装了JDK&#xff08;Java Development Kit&#xff09;&#xff0c;并且已经配置了JAVA_HOME环境变量。 接下来&#xff0c;您…

Inno setup 打包jar包+前端dist+mysql+navicat等应用文件操作

目录 一、 使用exe4j将后端jar包打包成exe应用文件 1.创建一个新的工程 2.选择一个你想要存放的路径 3.进入配置界面 4.选择jar转换exe模式 5.自定义名字和选择输出路径 6.配置初始化 7.配置java环境 8.测试运行结果 二、Inno 打包应用文件exe 1.新建一个工程文件 2…

main函数中argc和argv是什么意思

在C和C中&#xff0c;int main(int argc, char* argv[])语句作为程序的入口&#xff0c;在main函数中常常用到。 argc&#xff1a;argument count&#xff0c;参数的数量。argc是一个整型数&#xff0c;代表传入程序的命令行参数的数量。程序名称是第一个参数&#xff0c;所以…

【hashmap】【将排序之后的字符串作为哈希表的键】【获取 HashMap 中所有值的集合】Leetcode 49 字母异位词分组

【hashmap】【将排序之后的字符串作为哈希表的键】【获取 HashMap 中所有值的集合】Leetcode 49 字母异位词分组 解法1 将排序之后的字符串作为哈希表的键解法2 在解法一的基础上加入了getOrDefault ---------------&#x1f388;&#x1f388;题目链接&#x1f388;&#x1f3…

获取用户信息与token理解

获取用户信息和token是在开发Web应用程序时常见的需求&#xff0c;可以通过以下步骤来实现&#xff1a; 用户登录&#xff1a;用户在应用程序中输入用户名和密码进行登录验证。一旦验证成功&#xff0c;应用程序会生成一个唯一的token&#xff0c;并将其返回给客户端。存储tok…

Nginx http.server.location配置项说明

在 nginx.conf 的 server 块中的 location / { } 部分,你可以配置许多不同的参数来控制如何处理进入的请求和响应。以下是一些常用的 location 块配置参数: proxy_pass: 用于将请求代理到另一个服务器。例如:proxy_pass http://backend_server; proxy_set_header: 用于设置传…

核函数概念

基本概念 核函数是在机器学习领域&#xff0c;尤其是在支持向量机&#xff08;SVM&#xff09;算法中常用到的一个概念。核函数的基本想法是通过一个非线性变换将原始数据映射到一个更高维的空间&#xff0c;在这个新的空间中&#xff0c;原本线性不可分的数据可能变得线性可分…