代码随想录day23 | leetcode 39.组合总和 40.组合总和II

39.组合总和

Java

class Solution {     List<List<Integer>> result = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();public List<List<Integer>> combinationSum(int[] candidates, int target) {Arrays.sort(candidates);backtracking(candidates,target,0,0);return result;}public void backtracking(int[] candidates,int target,int sum,int startIndex){if (sum>target){return;}if (sum == target){result.add(new LinkedList<>(path));return;}for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {path.add(candidates[i]);sum += candidates[i];backtracking(candidates,target,sum,i);sum -= candidates[i];path.removeLast();}}
}
回溯方法:backtracking
public void backtracking(int[] candidates, int target, int sum, int startIndex) {if (sum > target) { // 剪枝:如果当前和已经超过目标,直接返回return;}if (sum == target) { // 找到满足条件的组合result.add(new LinkedList<>(path)); // 保存当前路径到结果return;}for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {path.add(candidates[i]); // 做选择:将当前数字加入路径sum += candidates[i]; // 更新路径总和backtracking(candidates, target, sum, i); // 递归,允许重复选择当前数字sum -= candidates[i]; // 撤销选择:恢复之前的状态path.removeLast(); // 从路径中移除最后一个数字,回溯}
}
逻辑解释
  1. 递归终止条件
    • sum > target:当前路径总和超过目标值,停止递归。
    • sum == target:找到一组符合条件的组合,将 path 复制加入结果。
  2. 循环递归
    • 循环起点:从 startIndex 开始,保证每次递归处理当前数字及其后续数字。
    • 条件:sum + candidates[i] <= target- 剪枝条件,提前终止无意义的递归。
    • 允许重复选择:- 递归调用时仍从 i 开始 (backtracking(candidates, target, sum, i)),因此当前数字可以重复加入组合。
  3. 回溯过程
    • path.add(candidates[i])path.removeLast():分别表示“选择当前数字”和“撤销选择”。
    • sum += candidates[i]sum -= candidates[i]:动态更新当前路径的总和。

40.组合总和II

树层去重一个数完整搜完一边,另一个重复的数不用搜第二遍

Java

class Solution {List<List<Integer>> result = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);boolean[] used = new boolean[candidates.length];Arrays.fill(used,false);backtracking(candidates,target,0,0,used);return result;}public void backtracking(int[] candidates, int target,int sum,int stateIndex,boolean[] used){if (sum>target){return;}if (sum == target){result.add(new ArrayList<>(path));}for (int i = stateIndex; i < candidates.length; i++) {if (i>0&&candidates[i-1]==candidates[i]&&used[i-1]==false){//重要,按层去重continue;}path.add(candidates[i]);sum += candidates[i];used[i] = true;backtracking(candidates,target,sum,i+1,used);path.removeLast();sum -= candidates[i];used[i] = false;}}
}

关键点

  1. 数组排序
	Arrays.sort(candidates);

对数组 candidates 进行排序是为了方便去重和剪枝。排序后,相同的元素会相邻,可以通过简单的逻辑避免重复。

  1. 去重逻辑
	if (i > 0 && candidates[i - 1] == candidates[i] && used[i - 1] == false) {continue;}

这一部分用于按“层”去重。如果当前元素与前一个元素相同,且前一个元素在当前层没有被使用(used[i - 1] == false),就跳过这个元素,避免重复组合。

  1. 递归与回溯
    • 递归条件:递归深入到下一层(选择下一个数字)。
    • 回溯操作:撤销上一步的选择(移除当前路径中的数字,恢复 sumused 的状态)。

代码逻辑

全局变量
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
  • result:存储最终的所有满足条件的组合。
  • path:存储当前递归路径上的数字组合。

主函数
public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates); // 排序,方便去重和剪枝boolean[] used = new boolean[candidates.length]; // 记录每个数字是否使用backtracking(candidates, target, 0, 0, used); // 初始状态return result;
}
  • 对数组排序后,初始化 used 数组为 false
  • 调用回溯函数 backtracking 开始寻找组合。

回溯函数
public void backtracking(int[] candidates, int target, int sum, int stateIndex, boolean[] used) {if (sum > target) {return; // 剪枝:当前组合和大于目标值}if (sum == target) {result.add(new ArrayList<>(path)); // 找到符合条件的组合,加入结果集return;}for (int i = stateIndex; i < candidates.length; i++) {if (i > 0 && candidates[i - 1] == candidates[i] && used[i - 1] == false) {continue; // 去重:跳过相同的元素}path.add(candidates[i]); // 添加当前数字到路径sum += candidates[i]; // 更新路径和used[i] = true; // 标记当前数字为已使用backtracking(candidates, target, sum, i + 1, used); // 递归到下一层path.removeLast(); // 回溯,撤销选择sum -= candidates[i]; // 恢复路径和used[i] = false; // 恢复使用状态}
}

重点逻辑

  1. 递归结束条件
    • sum > target 时,直接返回,表示当前路径无效。
    • sum == target 时,说明找到一个符合条件的组合,将其加入 result
  2. 去重
	if (i > 0 && candidates[i - 1] == candidates[i] && used[i - 1] == false) {continue;
}

按“层”去重。只有当前层的数字和前一个数字相同时,才需要检查是否跳过。
3. 递归与回溯
- 递归:将当前数字加入路径后,继续递归处理下一层。
- 回溯:撤销选择,包括移除路径中的数字,恢复 sumused 的状态。

131.分割回文串

Java

class Solution {List<List<String>> result = new ArrayList<>();LinkedList<String> path = new LinkedList<>();public List<List<String>> partition(String s) {backtracking(s,0);return result;}public void backtracking(String s,int startIndex){if (startIndex >= s.length()){result.add(new ArrayList<>(path));return;}for (int i = startIndex; i < s.length(); i++) {if (isPalindrome(s,startIndex,i)){String a = s.substring(startIndex,i+1);path.add(a);}else {continue;}backtracking(s,i+1);path.removeLast();}}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;}
}
全局变量
List<List<String>> result = new ArrayList<>();
LinkedList<String> path = new LinkedList<>();
  • result:存储所有满足条件的分割方案。
  • path:当前递归路径,表示当前的分割方案。

主函数
public List<List<String>> partition(String s) {backtracking(s, 0); // 从索引 0 开始划分字符串return result;
}
  • 调用回溯函数 backtracking 从字符串的第一个字符开始分割。
  • 返回所有满足条件的方案。

回溯函数
public void backtracking(String s, int startIndex) {if (startIndex >= s.length()) {result.add(new ArrayList<>(path)); // 如果遍历到字符串末尾,记录当前路径return;}for (int i = startIndex; i < s.length(); i++) {if (isPalindrome(s, startIndex, i)) { // 判断从 startIndex 到 i 的子串是否是回文String a = s.substring(startIndex, i + 1); // 取出当前回文子串path.add(a); // 加入路径} else {continue; // 如果不是回文,跳过本次循环}backtracking(s, i + 1); // 递归处理剩下的部分path.removeLast(); // 回溯,移除最后一个子串}
}
  • 终止条件:- 当 startIndex 超过或等于字符串长度时,说明已经分割完毕,记录当前路径。
  • 递归逻辑:- 从 startIndex 开始,尝试分割到每个可能的位置 i
    • 如果 s[startIndex...i] 是回文,则加入路径,并递归处理 s[i+1...end]
    • 递归返回后,回溯移除当前子串。

判断是否为回文
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; // 如果所有字符都相等,是回文
}
  • 双指针法,检查从 startend 的子串是否为回文。
  • 左右两端字符逐步比较,如果有任意一对不相等,则不是回文。

算法流程

  1. 从字符串 s 的第一个字符开始,尝试划分每个可能的回文子串。
  2. 如果找到一个回文子串,加入当前路径,并继续递归处理剩余部分。
  3. 当划分到字符串末尾时,将当前路径记录为一种有效方案。
  4. 回溯时移除最后一个子串,尝试其他划分方式。

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

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

相关文章

关于Buildroot如何配置qtwebengine [未能成功编译]

目录 前言 下载Buildroot 如何添加qtwebengine 开始make编译 编译过程中到了这些问题 前言 问题的开始就在于学习QT的过程中遇到了一个问题… Unknown module(s) in QT: webenginewidgets 我想要把qt的一个项目编译并发送到我的开发板上&#xff0c;但是qmake识别不到这…

SNP与Scheer合作助力Warsteiner Brauerei成功升级至SAP S/4HANA

德国软件和咨询公司SNP是SAP环境中数字化转型、自动化数据迁移和数据管理软件的知名提供商&#xff0c;再次与德国Scheer公司合作&#xff0c;Scheer公司是一家专门从事业务流程管理和SAP咨询的咨询公司。他们为家族企业Warsteiner Brauerei Haus Cramer KG向SAP S/4HANA升级转…

【Super Tilemap Editor使用详解】(五):图块调色板

1、图块调色板&#xff08;Tile Palette&#xff09;可以在以下位置找到&#xff1a; Tileset Inspector检视面板 STETilemap Inspector检视面板&#xff0c;并选择 "Paint" 选项卡 Tile Palette 窗口&#xff1a;"SuperTilemapEditor/Window/Tile Palette Win…

LNMP+discuz论坛

0.准备 文章目录 0.准备1.nginx2.mysql2.1 mysql82.2 mysql5.7 3.php4.测试php访问mysql5.部署 Discuz6.其他 yum源&#xff1a; # 没有wget&#xff0c;用这个 # curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo[rootlocalhost ~]#…

TRELLIS,一键生成3D模型,图像转3D,微软开源

大家好&#xff01;今天给大家分享微软最近开源的一个3D模型生成项目——TRELLIS。简单来说就是输入一张图片&#xff0c;它就能自动帮你生成3D模型。这与之前分享的TripoSR项目类似&#xff0c;但是精度和贴图细节比TripoSR要高很多。 好久没关注AI生成3D模型这块&#xff0c;…

开源架构学习指南:文档与资源的智慧锦囊

开源架构学习指南&#xff1a;文档与资源的智慧锦囊 一、引言二、开源架构文档的核心价值剖析&#xff08;一&#xff09;知识传承与共享&#xff1a;智慧的薪火相传1. 经典案例&#xff1a;Linux 内核文档 —— 开源世界的智慧基石 &#xff08;二&#xff09;促进协作与沟通&…

景联文科技:精准语音标注,驱动语音技术新发展

在人工智能迅速发展的今天&#xff0c;语音技术的应用已经渗透到我们生活的方方面面。从智能音箱、语音助手到自动语音识别系统&#xff0c;高质量的语音数据是这些应用成功的关键。景联文科技作为领先的AI数据服务提供商&#xff0c;专注于为客户提供高精度、高效的语音标注服…

HTTP接口报错详解与解决 200,500,403,408,404

前言&#xff1a; 仅做学习记录&#xff0c;侵删 背景 当后端编写接口时&#xff0c;经常需要对接口使用ApiFox或者PostMan进行测试&#xff0c;此时就会出现各种各样的报错&#xff0c;一般都会包括报错编码&#xff1a;200,400,401等。这个状态码一般是服务器所返回的包含…

NVIDIA发布紧凑型生成式AI超级计算机:性能提升,价格更低

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

upload-labs(1-19关)通关攻略

Pass-01 本关思路&#xff1a;删除前端js校验 进入第一关环境 桌面新建一个php文件&#xff0c;命名为1.php <?php eval($_POST[a]);?> 我们上传此文件&#xff0c;发现不允许上传&#xff0c;且页面没有变化&#xff0c;说明前端进行了拦截 这时我们打开 F12 &…

【开源库 | minizip】Linux(Ubuntu18.04)下,minizip的编译、交叉编译

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 2024-12-20 …

uniapp地址类 方法

关于点击没反应 manifest.json 检查是否添加了对应的权限 /* 小程序特有相关 */"mp-weixin" : {"appid" : "wxc481f10754f1d9df","setting" : {"urlCheck" : false,"es6" : true,"postcss" : true,&qu…

WebContainerapi 基础(Web IDE 技术探索 一)

前言 随着web技术的发展&#xff0c;在网页端直接运行node.js、实现微型操作系统已经不再是难事。今天介绍的 WebContainers就是一个基于浏览器的运行时&#xff0c;用于执行 Node.js 应用程序和操作系统命令&#xff0c;它完全运行在您的浏览器页面中&#xff0c;提供了文件系…

【爬虫开发】爬虫开发从0到1全知识教程第11篇:Mongodb数据库,介绍【附代码文档】

本教程的知识点为&#xff1a;爬虫概要 爬虫基础 爬虫概述 知识点&#xff1a; 1. 爬虫的概念 requests模块 requests模块 知识点&#xff1a; 1. requests模块介绍 1.1 requests模块的作用&#xff1a; 数据提取概要 数据提取概述 知识点 1. 响应内容的分类 知识点&#xff1a…

FFmpeg 安装教程(Windows 系统)

1. 前言 FFmpeg 是一个用于处理视频、音频等多媒体文件的开源工具包。它支持几乎所有的多媒体格式转换、剪辑和编辑&#xff0c;是开发者和多媒体工作者必备的工具。本文详细讲解如何在 Windows 系统上安装 FFmpeg 并进行基本配置。 2. 下载 FFmpeg 安装包 打开 Dpwnload FFmp…

【AutoDL】通过【SSH远程连接】【vscode】

小帅碎碎念 0. 起因1. SSH信息获取2. 给你的vscode安装支持SSH远程连接的插件3. SSH远程连接入口4. 输入密码登陆5. 总结 0. 起因 之前使用AutoDL和Jupyter进行代码编辑和执行确实很方便&#xff0c;尤其是对于交互式数据分析项目。然而&#xff0c;也存在一些限制和不便之处&…

C# 识别二维码

文章目录 一. 二维码识别技术概述二 维码识别的步骤图像预处理二维码的定位和检测二维码解码 三 常用的二维码识别库1. OpenCV2. ZXing.Net 一. 二维码识别技术概述 二维码是一种通过黑白矩阵排列来编码数据的图形符号&#xff0c;它的编码方式具有较强的容错性&#xff0c;可以…

如何在 Linux 服务器上部署 Pydio Cells 教程

简介 Pydio Cells 是一个开源的文档共享和协作平台&#xff0c;专为你的组织设计。它允许你在组织内部分享文档和文件&#xff0c;并让你完全掌控文档共享环境。 在本教程中&#xff0c;我们将向你展示如何在 Alma Linux 9 服务器上安装 Pydio Cells。你将使用 MariaDB 数据库…

OkHttp源码分析:分发器任务调配,拦截器责任链设计,连接池socket复用

目录 一&#xff0c;分发器和拦截器 二&#xff0c;分发器处理异步请求 1.分发器处理入口 2.分发器工作流程 3.分发器中的线程池设计 三&#xff0c;分发器处理同步请求 四&#xff0c;拦截器处理请求 1.责任链设计模式 2.拦截器工作原理 3.OkHttp五大拦截器 一&#…

(2024年最新)Linux(Ubuntu) 中配置静态IP(包含解决每次重启后配置文件失效问题)

Hello! 亲爱的小伙伴们&#xff0c;大家好呀&#xff08;Smile~&#xff09;&#xff01;我是Huazzi&#xff0c;欢迎观看本篇博客&#xff0c;接下来让我们一起来学习一下Ubuntu 中如何配置静态IP吧&#xff01;祝你有所收获&#xff01; 提前对Linux有所了解的小伙伴应该知道…