当前位置: 首页 > news >正文

代码随想录day23 | leetcode 39.组合总和 40.组合总和II 131.分割回文串

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. 回溯时移除最后一个子串,尝试其他划分方式。

相关文章:

代码随想录day23 | leetcode 39.组合总和 40.组合总和II 131.分割回文串

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.sor…...

全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)

if语句处理多个分支时需要用if-else if结构&#xff0c;分支越多&#xff0c;嵌套的if语句层就越多&#xff0c;程序不但庞大、复杂&#xff0c;理解起来也比较困难。在C编程中&#xff0c;针对有些问题除了使用if-else if结构之外&#xff0c;还有switch语句也可以实现&#x…...

R机器学习:决策树算法的理解与实操

今天继续给大家介绍决策树算法&#xff0c;决策树本身是一种非常简单直观的机器学习算法&#xff0c;用于做分类或回归任务。它就像我们平常做决定时的过程&#xff0c;通过逐步排除可能的选项&#xff0c;最终得出结论。 A decision tree is a flowchart-like structure used …...

解锁高效学习之道:从认知升级到实践突破

目录 学习之困&#xff1a;探寻低效的根源 &#xff08;一&#xff09;迷茫之境&#xff1a;目标缺失的困扰 &#xff08;二&#xff09;表象之迷&#xff1a;浅尝辄止的学习 &#xff08;三&#xff09;行动之阻&#xff1a;执行力的短板 认知重塑&#xff1a;明晰学习的本…...

2024年12月CCF-GESP编程能力等级认证Python编程三级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 一、单选题(每题 2 分,共 30 分) 第 1 题 2024年10月8日,诺贝尔物理学奖“意外地”颁给了两位计算机科学家约翰霍普菲尔德(John J. Hopfield)和杰弗里辛顿(Geof…...

.NET Core 中使用 C# 获取Windows 和 Linux 环境兼容路径合并

在 .NET Core 中使用 C# 处理路径合并并确保在 Windows 和 Linux 环境中都能正常工作&#xff0c;可以使用 System.IO.Path 和 System.IO.Path.Combine 方法。它们是跨平台的&#xff0c;能够根据操作系统自动处理路径分隔符。可以通过 System.Runtime.InteropServices.Runtime…...

【SH】Ubuntu Server 24服务器搭建MySQL数据库研发笔记

文章目录 搭建服务器在线安装1. 更新软件包列表2. 安装MySQL3. 检查MySQL状态4. 修改密码5. 新增用户6. 设置局域网访问 离线安装下载安装包 常用命令参考文档在线安装日志 搭建服务器 作者羊大侠搭建的是 Ubuntu Server 24.04 LTS 服务器环境 搭建参考文档&#xff1a;【SH】…...

编译原理复习---正则表达式+有穷自动机

适用于电子科技大学编译原理期末考试复习。 1. 正则表达式 正则表达式&#xff08;Regular Expression&#xff0c;简称regex或regexp&#xff09;是一种用于描述、匹配和操作文本模式的强大工具。它由一系列字符和特殊符号组成&#xff0c;这些字符和符号定义了一种搜索模式…...

知识图谱+RAG学习

GraphRAG&#xff08;Graph-based Retrieval-Augmented Generation&#xff09;是微软在2024年推出的一项开源技术&#xff0c;旨在通过结合知识图谱和检索增强生成&#xff08;RAG&#xff09;方法&#xff0c;为大型语言模型&#xff08;LLM&#xff09;的数据处理提供全新解…...

消息队列技术的发展历史

消息队列技术的演进历程宛如一幅波澜壮阔的科技画卷&#xff0c;历经多个标志性阶段&#xff0c;各阶段紧密贴合不同的技术需求与市场风向&#xff0c;下面为您详细道来。 第一阶段&#xff1a;消息中间件的起源&#xff08;1970 年代末期 - 1980 年代中期&#xff09; 在计算…...

每天40分玩转Django:Django部署

Django部署 一、今日学习内容概述 学习模块重要程度主要内容生产环境配置⭐⭐⭐⭐⭐settings配置、环境变量WSGI服务器⭐⭐⭐⭐⭐Gunicorn配置、性能优化Nginx配置⭐⭐⭐⭐反向代理、静态文件安全设置⭐⭐⭐⭐⭐SSL证书、安全选项 二、生产环境配置 2.1 项目结构调整 mypr…...

搭建Elastic search群集

一、实验环境 二、实验步骤 Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎Elasticsearch目录文件&#xff1a; /etc/elasticsearch/elasticsearch.yml#配置文件 /etc/elasticsearch/jvm.options#java虚拟机 /etc/init.d/elasticsearch#服务启动脚本 /e…...

解析 Ingress-Nginx 故障:排查思路与方法

文章目录 一、什么是Ingress-Nginx二、故障排除1.1Ingress-Controller日志和事件检查 Ingress 资源事件检查 Nginx 配置检查使用的服务是否存在调试日志 1.2对 Kubernetes API 服务器的认证服务认证服务账户Kube-Config 1.3使用GDB和Nginx1.4在 Nginx 4.2.5 或其他版本&#xf…...

2024 楚慧杯 re wp

go_bytes 附件拖入ida 输入长度为0x28&#xff0c;每两位字符的4bit拼接 与一个常量值经过运算后的值进行异或&#xff0c;并且判断是否相等 脚本 bouquet 附件拖入ida。简单去一下花 构建了一个二叉树&#xff0c;然后递归调用函数 重新排列一下再层序遍历读出即可 zistel 附件…...

【物联网技术与应用】实验10:蜂鸣器实验

实验10 蜂鸣器实验 【实验介绍】 蜂鸣器是音频信号装置。蜂鸣器可分为有源蜂鸣器和无源蜂鸣器。 【实验组件】 ● Arduino Uno主板* 1 ● USB数据线* 1 ● 有源蜂鸣器* 1 ● 无源蜂鸣器* 1 ● 面包板* 1 ● 9V方型电池* 1 ● 跳线若干 【实验原理】 如图所示&#x…...

单片机:实现矩阵键盘控制LCD屏幕(附带源码)

单片机实现矩阵键盘控制LCD屏幕 矩阵键盘&#xff08;Matrix Keypad&#xff09;是一种常用的输入设备&#xff0c;广泛应用于嵌入式系统中。在许多嵌入式应用中&#xff0c;我们常常需要通过按键输入来控制系统的功能。结合LCD显示屏&#xff0c;我们可以实现一个简单的界面&…...

鸿蒙Next之包体积极限优化

鸿蒙应用包大小优化全解析 在鸿蒙应用开发中&#xff0c;减小应用包大小对于提升应用下载和安装体验起着关键作用。通过压缩、精简或复用应用中的代码与资源&#xff0c;能有效降低包体积&#xff0c;减少空间占用并加快下载与安装速度。下面详细介绍一下鸿蒙应用包大小优化的…...

Android实战经验篇-log工具

详细代码实现及系列文章请转如下链接 Android实战经验篇-系列文章汇总 Android Display Graphics系列文章-汇总 一、基础知识 1.1 Logging简述 我们写的第一个计算机C程序一般是printf(“Hello world!”);这就是一个log输出。Linux内核有Kernel log以及配套的Log工具&#x…...

DPU编程技术解析与实践应用

一、引言 1.1 研究背景与目的 随着信息技术的飞速发展&#xff0c;数据中心在现代社会中的地位日益凸显&#xff0c;成为支撑各行业数字化转型的关键基础设施。在数据中心内部&#xff0c;数据的处理速度、效率和安全性成为了影响整体性能的核心要素。为了应对不断增长的数据…...

红帽认证的含金量和价值如何?怎么报名红帽认证考试?

红帽企业 Linux&#xff08;RHEL&#xff09;是由红帽公司提供的一款商业支持、专为生产环境设计的Linux发行版。随着IT系统和工作负载日益复杂化&#xff0c;底层基础设施及操作系统必须兼具可靠性、可扩展性&#xff0c;并能有效促进性能提升。红帽认证在全球范围享有盛誉&am…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...