【LeetCode 每日一题】712. 两个字符串的最小ASCII删除和——(解法三)状态压缩

Problem: 712. 两个字符串的最小ASCII删除和

文章目录

整体思路

1. 核心问题与转换

这段代码依然沿用了 “总和 - 最大公共子序列(LCS)权重” 的逆向思维策略。
核心公式保持不变:
最小删除和 = ( s1总和 + s2总和 ) − ( LCS字符ASCII和 × 2 ) \text{最小删除和} = (\text{s1总和} + \text{s2总和}) - (\text{LCS字符ASCII和} \times 2) 最小删除和=(s1总和+s2总和)−(LCS字符ASCII和×2)

2. 算法优化:状态压缩(1D DP)

与上一版二维数组解法不同,这里使用了一维数组进行空间优化。

  • 空间压缩原理
    在二维 DP 中,计算 dp[i][j] 只需要用到上一行的数据 dp[i-1][...] 和当前行左边的数据 dp[i][j-1]
    • f[j+1] 在更新前,存储的是上一行对应位置的值(相当于 dp[i-1][j])。
    • f[j] 在更新后,存储的是当前行左边位置的值(相当于 dp[i][j-1])。
    • 难点:在于如何获取 dp[i-1][j-1](左上角的值)。因为在更新 f[j+1] 之前,f[j] 已经被更新为当前行的值了。
    • 解决方案:引入 pre 变量,专门用来暂存上一行对角线位置的值。
  • 逻辑流程
    1. 初始化长度为 m + 1 的数组 f,初始全为 0(代表空串时的公共和)。
    2. 外层循环遍历 s1 的字符 x
    3. 在内层循环开始前,初始化 pre = 0(代表第 0 列的左上角,即空前缀)。
    4. 内层循环遍历 s2 的索引 j
      • 先用 temp 保存 f[j+1] 的旧值(即下一轮需要的左上角值)。
      • 根据 xt[j] 是否相等,利用 pref[j+1](旧)、f[j](新)更新 f[j+1]
      • 更新 pre = temp,为下一个位置做准备。

完整代码

classSolution{publicintminimumDeleteSum(String s1,String s2){// 1. 计算两字符串初始的总 ASCII 和int sum = s1.chars().sum()+ s2.chars().sum();char[] s = s1.toCharArray();char[] t = s2.toCharArray();int m = t.length;// 2. 创建一维 DP 数组// f[k] 表示 s1 当前处理到的前缀与 s2 的前 k 个字符的最大公共 ASCII 权重和int[] f =newint[m +1];// Java 中 int 数组默认初始化为 0,符合逻辑(空串的公共和为 0)// 外层循环:遍历 s1 的每个字符 xfor(char x : s){// pre 用于维护 "左上角" (diagonal) 的状态// 相当于二维 DP 中的 dp[i-1][j-1]// 对于每一行的第一个元素,其左上角是 f[0],始终为 0int pre =0;// 内层循环:遍历 s2 的每个位置 jfor(int j =0; j < m; j++){// temp 暂存 f[j+1] 在更新前的值// 这个值对应二维 DP 中的 dp[i-1][j] (上一行的值)// 在下一次循环 (j+1) 时,它将变成 "左上角" (pre)int temp = f[j +1];// 状态转移逻辑if(x == t[j]){// 字符匹配:// 当前值 = 左上角值 (pre) + 当前字符 ASCII * 2 f[j +1]= pre + x *2;}else{// 字符不匹配:// 取 "上方" (f[j+1] 旧值) 和 "左方" (f[j] 新值) 的最大值 f[j +1]=Math.max(f[j +1], f[j]);}// 更新 pre,将当前的旧值传递给下一次内层循环作为左上角使用 pre = temp;}}// 3. 计算结果// 总和 - 最大保留部分的和return sum - f[m];}}

时空复杂度

1. 时间复杂度: O ( N × M ) O(N \times M) O(N×M)

  • 计算依据
    • 双重循环结构没有改变。
    • 外层循环执行 N N N 次(s1 的长度),内层循环执行 M M M 次(s2 的长度)。
    • 内部操作均为 O ( 1 ) O(1) O(1)。
  • 结论: O ( N × M ) O(N \times M) O(N×M)。

2. 空间复杂度: O ( M ) O(M) O(M)

  • 计算依据
    • 这是此代码的主要亮点。
    • 我们将原本 ( N + 1 ) × ( M + 1 ) (N+1) \times (M+1) (N+1)×(M+1) 的二维数组压缩为了长度为 M + 1 M+1 M+1 的一维数组 f
    • 额外使用了几个常数变量(pre, temp 等)。
    • 空间消耗仅与 s2 的长度线性相关。
  • 结论: O ( M ) O(M) O(M),其中 M M M 是 s2 的长度。
    • 优化提示:如果 N < M N < M N<M,可以在代码开始前交换 s1s2,使空间复杂度进一步优化为 O ( min ⁡ ( N , M ) ) O(\min(N, M)) O(min(N,M))。

Read more

Spring Boot 实战:MyBatis 操作数据库(上)

Spring Boot 实战:MyBatis 操作数据库(上)

—JavaEE专栏— Spring Boot 实战:MyBatis 操作数据库(上) 摘要 本文深度解析了 Spring Boot 环境下 MyBatis 的集成与应用。通过回顾传统 JDBC 的局限性,详细展示了 MyBatis 在日志配置、CRUD 操作、自增主键返回及多表查询中的实战用法。同时,文章深入探讨了 #{} 与 ${} 的底层预编译差异及安全风险,并分享了企业级开发中的数据库命名规范与 Druid 连接池配置,助力开发者构建稳健的持久层架构。 文章目录 * Spring Boot 实战:MyBatis 操作数据库(上) * 摘要 * @[toc] * 1. 为什么持久层开发需要 MyBatis? * 1.1 传统 JDBC 的局限性 * 1.2

By Ne0inhk
FARS全自动科研系统技术深度解析:从多智能体架构到工业化科研范式

FARS全自动科研系统技术深度解析:从多智能体架构到工业化科研范式

前言 2026年2月12日至2月22日,一场持续228小时33分钟的直播在全球AI社区引发了持续震荡。屏幕另一端,一个名为FARS(Fully Automated Research System)的全自动研究系统,在没有人类干预的情况下,自主完成了从文献调研到论文撰写的完整科研流程,最终产出100篇学术论文,总消耗114亿Token,成本10.4万美元。 这场实验的意义远不止于“AI写论文”的简单升级。它向世界展示了科学发现的根本范式正在发生转移——从依赖人类灵感的“手工作坊”,转向由AI驱动的“工业化流水线”。本文将从最底层的技术细节出发,逐层拆解FARS的系统架构、智能体协作机制、资源调度策略、成本控制模型,以及与竞品的技术对比,为读者呈现一个完整的全自动科研系统技术图谱。 第一章 系统总体架构:四智能体流水线设计 1.1 核心设计理念:研究系统的第一性原理 FARS的设计并非简单地模仿人类科研流程,而是基于团队对“研究系统”本质的重新思考。创始团队提出,一个理想的研究系统应遵循两条基本原则: 1. 高效拓展知识边界:系统的吞吐量应成为核心评估指标,而非单篇论文的完

By Ne0inhk
Web足球青训俱乐部管理后台系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

Web足球青训俱乐部管理后台系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

摘要 随着足球运动的普及和青少年体育教育的重视,足球青训俱乐部在培养年轻球员方面发挥着越来越重要的作用。然而,传统的俱乐部管理方式往往依赖手工操作和纸质记录,效率低下且容易出错。信息技术的快速发展为俱乐部管理提供了新的解决方案,通过数字化手段提升管理效率和数据准确性成为迫切需求。该系统旨在为足球青训俱乐部提供一个高效、便捷的管理平台,涵盖学员信息、训练计划、赛事安排等核心功能,帮助俱乐部实现规范化、智能化管理。关键词:足球青训、俱乐部管理、数字化、效率提升、规范化。 本系统采用前后端分离架构,后端基于SpringBoot框架实现,提供稳定高效的API接口;前端使用Vue.js构建,确保用户界面的流畅性和交互体验;数据库采用MySQL,保证数据存储的安全性和可扩展性。系统功能模块包括学员信息管理、训练计划制定、赛事记录统计、教练员管理等,支持数据的增删改查和多条件筛选。通过权限控制实现不同角色的差异化操作,确保数据安全性。系统源码可直接运行,便于二次开发和部署。关键词:SpringBoot、Vue.js、MySQL、权限控制、数据管理。 数据表 学员信息数据表 学员信息数据表中

By Ne0inhk
Spring Boot 消息队列与异步通信

Spring Boot 消息队列与异步通信

Spring Boot 消息队列与异步通信 21.1 学习目标与重点提示 学习目标:掌握Spring Boot消息队列与异步通信的核心概念与使用方法,包括消息队列的定义与特点、Spring Boot与ActiveMQ的集成、Spring Boot与RabbitMQ的集成、Spring Boot与Kafka的集成、Spring Boot异步通信的基本方法、Spring Boot的实际应用场景,学会在实际开发中处理消息队列与异步通信问题。 重点:消息队列的定义与特点、Spring Boot与ActiveMQ的集成、Spring Boot与RabbitMQ的集成、Spring Boot与Kafka的集成、Spring Boot异步通信的基本方法、Spring Boot的实际应用场景。 21.2 消息队列概述 消息队列是Java开发中的重要组件。 21.2.1 消息队列的定义 定义:消息队列是一种异步通信机制,用于在应用程序之间传递消息。 作用: * 实现应用程序之间的异步通信。 * 实现应用程序之间的解耦。 * 提高应用程序的性能。 常见的消息队列: * Activ

By Ne0inhk