Problem: 32. 最长有效括号

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N)
    • 空间复杂度:O(N)

整体思路

这段代码同样旨在解决 “最长有效括号” 问题,但它采用的是一种 动态规划 (Dynamic Programming) 的方法。这种方法通过构建一个DP表(dp 数组),从左到右逐步计算以每个字符为结尾的最长有效括号子串的长度。

算法的核心在于定义状态 dp[i] 并找出其状态转移关系。

  1. 状态定义

    • dp[i] 被定义为:以字符串 s 中第 i-1 个字符(即 s.charAt(i-1))为结尾的最长有效括号子串的长度
    • 索引偏移:为了方便处理边界,代码在原始字符串 s 前面加了一个空格 " ",使得 s 的索引从1开始。这样,dp 数组的索引 i 就直接对应了新字符串的索引 i
  2. 状态转移方程

    • dp[i] 的值只有在 s.charAt(i) 是一个右括号 ')' 时才可能大于0,因为一个有效的括号子串必然以 ')' 结尾。如果 s.charAt(i)'('dp[i] 默认为0。
    • s.charAt(i) == ')' 时,我们需要寻找一个与之匹配的左括号 '('。这里有两种主要情况:
      a. 情况 1:形如 ...()
      • 如果 s.charAt(i-1) 是一个 '(',那么 s.charAt(i)s.charAt(i-1) 构成了最简单的一对有效括号 ()
      • 这个 () 的长度是 2。它还可以连接在 s.charAt(i-2) 结尾的有效子串后面。
      • 因此,状态转移方程为:dp[i] = dp[i-2] + 2
        b. 情况 2:形如 ...))
      • 如果 s.charAt(i-1) 也是一个 ')',那么 s.charAt(i) 需要去匹配更左边的某个 '('
      • 我们知道,以 s.charAt(i-1) 结尾的有效子串长度是 dp[i-1]。那么,这个子串的起始位置就是 i - 1 - dp[i-1] + 1。它所需要匹配的左括号就在这个起始位置的前一个,即索引 i - 1 - dp[i-1] 的位置。
      • 我们检查 s.charAt(i - 1 - dp[i-1]) 是否为 '('
      • 如果匹配成功
        • 新形成的这个大括号 (...) 的长度是 dp[i-1] + 2
        • 并且,这个大括号还可以连接在它前面的另一个有效子串后面。这个“前面的有效子串”是以 s.charAt(i - 2 - dp[i-1]) 结尾的,其长度为 dp[i - 2 - dp[i-1]]
        • 因此,总长度为:dp[i] = dp[i-1] + 2 + dp[i - 2 - dp[i-1]]
  3. 最终结果

    • 在填充 dp 数组的过程中,dp[i] 只是以 s.charAt(i) 为结尾的最长长度。全局的最长长度可能是任何一个 dp[i] 的值。
    • 因此,需要一个 ans 变量来实时记录并更新所有 dp[i] 中的最大值。

完整代码

class Solution {/*** 找到字符串中最长的有效括号子串的长度。* @param s 只包含 '(' 和 ')' 的字符串* @return 最长有效括号子串的长度*/public int longestValidParentheses(String s) {// ans: 用于存储全局的最长有效括号子串长度。int ans = 0;// 技巧:在 s 前面加一个空格,使得索引从 1 开始,方便处理边界情况 dp[i-2]。s = " " + s;// dp 数组:dp[i] 表示以 s.charAt(i) 结尾的最长有效括号子串的长度。int[] dp = new int[s.length()];// 从索引 2 开始遍历,因为最短的有效括号 "()" 长度为 2。for (int i = 2; i < s.length(); i++) {// 只在遇到右括号时才可能形成有效子串if (s.charAt(i) == ')') {// 情况 1: 子串形如 ".....()"if (s.charAt(i - 1) == '(') {// 长度 = 前面有效子串的长度 (dp[i-2]) + "()" 的长度 (2)dp[i] = dp[i - 2] + 2;} // 情况 2: 子串形如 ".....))"// 且 s.charAt(i-1) 结尾的子串是有效的 (dp[i-1] > 0)// 我们需要检查 s[i-1-dp[i-1]] 是否是与之匹配的'('else if (i - 1 - dp[i - 1] > 0 && s.charAt(i - 1 - dp[i - 1]) == '(') {// 长度 = s[i-1]结尾的子串长度 + 新匹配的"()"长度 + 更前面连接的有效子串长度dp[i] = dp[i - 1] + 2 + dp[i - 2 - dp[i-1]];}}// 每次计算完 dp[i]后,都用它来更新全局最大值 ans。ans = Math.max(ans, dp[i]);}return ans;}
}

时空复杂度

时间复杂度:O(N)

  1. 字符串拼接s = " " + s; 在Java中会创建一个新的字符串,这需要 O(N) 的时间。
  2. 循环:算法的核心是一个 for 循环,它从 i = 2 遍历到 s.length() - 1。这个循环严格地执行 N-1 次(N 为原字符串长度)。
  3. 循环内部操作
    • 在循环的每一次迭代中,执行的都是常数次的操作:字符访问 charAt()、数组访问 dp[]、加减法和 Math.max
    • 这些操作的时间复杂度都是 O(1)

综合分析
算法的总时间复杂度是 O(N) (字符串拼接) + O(N) (循环) = O(N)

空间复杂度:O(N)

  1. 主要存储开销
    • String s = " " + s;: 创建了一个新的字符串对象,其长度为 N+1,占用了 O(N) 的空间。
    • int[] dp = new int[s.length()]: 创建了一个 dp 数组,其长度也为 N+1,占用了 O(N) 的空间。

综合分析
算法所需的额外空间主要由新的字符串对象和 dp 数组决定。因此,其空间复杂度为 O(N)

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

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

相关文章

使用Docker部署ZLMediaKit流媒体服务器实现gb/t28181协议的设备

最近在研究一个摄像头&#xff0c;通信协议是 gb/t28181。对于这个协议也是第一次接触&#xff0c;通过查阅多方资料&#xff0c;找到了两个开源的源码&#xff0c;来实现 视频播放、摄像头直播。以前也没有深入的了解过关于视频播放的这方面的技术&#xff0c;偶尔网站播放视频…

硬件三人行--运算基础篇

第3讲 负反馈放大电路

【LINUX网络】TCP原理

目录 本文介绍 1. 什么是TCP&#xff1f; 2. TCP结构 为什么需要协议栈&#xff1a;两台主机通信的复杂性解决方案 3. 确认应答机制 进一步理解什么是确认和请求以及序号 进一步理解什么是序号和确认序号 并发发送带来的问题以及解决方案&#xff08;序号&#xff09; …

Java -- 文件基础知识--Java IO流原理--FileReader

目录 1. 常用文件操作 2. Java IO流原理 2.1 流的分类 3. FileReader和FileWriter介绍 FileReader相关方法&#xff1a; FileWriter常用方法&#xff1a; 文件是保存数据的地方&#xff0c;比如大家经常使用的word文档&#xff0c;txt文件&#xff0c;excel文件...都是文…

向量方法证明正余弦定理的数学理论体系

向量方法证明正余弦定理的数学理论体系 摘要&#xff1a; 向量理论为几何定理的证明提供了强有力的代数化工具。本文基于向量空间的基本概念与运算性质&#xff0c;严格推导平面几何中的正弦定理与余弦定理。通过建立系统的向量表示框架&#xff0c;将几何关系转化为向量运算&a…

【笔记ing】大模型算法架构

前言 随着人工智能技术的飞速发展,大模型算法及其架构已成为推动科技前沿的重要力量。它们不仅能够处理海量的数据,还具备强大的表征学习能力,能够应对日益复杂的场景需求。本章节将介绍大模型算法及其架构,带您了解其背后的原理、技术创新以及在实际应用中的广阔前景。 …

ConcurrentHashMap的原理

1.底层数据结构JDK1.7底层采用分段的数组链表实现JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组链表/红黑二叉树2.加锁的方式JDK1.7采用Segment分段锁,底层使用的是ReentrantLockJDK1.8采用CAS添加新节点,采用synchronized锁定链表或红黑二叉树的首节点,相对Segment分段锁…

【论文阅读】健全个体无辅助运动期间可穿戴传感器双侧下肢神经机械信号的基准数据集

Benchmark Datasets for Bilateral Lower-Limb Neuromechanical Signals from Wearable Sensors during Unassisted Locomotion in Able-Bodied Individuals 原文&#xff1a;DOI&#xff1a; 10.3389/frobt.2018.00014 2018年 翻译&#xff1a;靠岸学术 目录 1引言 2仪器设…

反向海淘系统搭建:从架构设计到合规运营的全方位指南

一、系统架构设计1.1 分层架构设计反向海淘系统通常采用四层架构设计&#xff1a;‌接入层‌&#xff1a;负责与淘宝开放平台、1688海外接口通信&#xff0c;处理接口认证、请求转发与响应解析。‌业务层‌&#xff1a;包含商品检索、订单管理、支付处理、物流追踪等核心模块。…

20.22 QLoRA微调实战:中文语音识别数据准备全流程解密

QLoRA微调实战:中文语音识别数据准备全流程解密 实战项目:QLoRA 微调数据准备详解 本环节我们将以中文语音识别任务为场景,详细拆解 QLoRA 微调前的数据准备流程。以下流程图展示了完整的数据处理路径: #mermaid-svg-A3ZpWn1ysZUg6jg4 {font-family:"trebuchet ms&q…

工业电子看板赋能线缆工厂生产高效运转

在制造业智能化转型的浪潮中&#xff0c;工业电子看板已不再只是“显示数据的屏幕”&#xff0c;而是成为连接设备层、控制层与管理层的实时信息枢纽。尤其在线缆制造这类对工艺参数敏感、生产连续性要求高的行业中&#xff0c;电子看板通过对关键数据的透明化、实时化与交互化…

Java爬虫是什么,如何获取API接口

一、Java爬虫的定义Java爬虫是一种基于Java编程语言开发的网络爬虫程序。它通过模拟浏览器行为&#xff0c;向目标网站发送HTTP请求&#xff0c;获取网页内容并解析出所需数据。Java爬虫技术广泛应用于数据采集、市场分析、竞争情报等领域。二、Java爬虫获取API接口的方法&…

Python篇---返回类型

基础返回类型&#xff1a;在 Python 中&#xff0c;函数的返回类型就像函数 “产出” 的不同 “物品”&#xff0c;理解它们能帮你更好地控制代码的输出。下面用通俗的方式介绍常见的返回类型及用法&#xff1a;一、最基础的返回类型1. 无返回值&#xff08;None&#xff09;特…

ArkTS 与 TypeScript 的关系及鸿蒙开发常见错误案例

随着 HarmonyOS NEXT&#xff08;纯血鸿蒙&#xff09; 的到来&#xff0c;开发者在学习鸿蒙应用开发时会遇到一个新的语言 —— ArkTS。很多人会疑惑&#xff1a;它和 TypeScript&#xff08;TS&#xff09;是什么关系&#xff1f;又有哪些新的特性&#xff1f;在实际开发中&a…

初识socket编程(实现一个简单的TCPServer)

监听套接字的创建流程 在网络编程中&#xff0c;listen 套接字&#xff08;通常称为“监听套接字”&#xff09;是服务器端用于接收客户端连接请求的特殊套接字&#xff0c;是 TCP 服务器建立连接过程中的核心组件。下面我们就来简单看一下监听套接字创建的过程创建流程&#x…

开发者如何在 Gitee 上开源一个自己的项目

文章目录一、为什么要在 Gitee 上开源&#xff1f;1. 开源的价值2. 为什么是 Gitee&#xff1f;二、前期准备&#xff1a;让项目“可开源”1. 项目代码整理2. 添加必要文件3. 确定开源许可证三、在 Gitee 上创建仓库四、推送本地代码到 Gitee五、完善项目展示&#xff08;吸引力…

卷积神经网络实现mnist手写数字集识别案例

手写数字识别是计算机视觉领域的“Hello World”&#xff0c;也是深度学习入门的经典案例。它通过训练模型识别0-9的手写数字图像&#xff08;如MNIST数据集&#xff09;&#xff0c;帮助我们快速掌握神经网络的核心流程。本文将以PyTorch框架为基础&#xff0c;带你从数据加载…

实战笔记——构建智能Agent:SpreadJS代码助手

目录 前言 解决思路 需求理解 MCP Server LangGraph 本教程目标 技术栈 第一部分&#xff1a;构建 MCP Server - 工具服务化的基础架构 第二部分&#xff1a;Tools 实现 第三部分&#xff1a;基于 LangGraph 构建智能 Agent 第四部分&#xff1a;服务器和前端搭建 前…

【Word】用 Python 轻松实现 Word 文档对比并生成可视化 HTML 报告

在日常工作和学习中&#xff0c;我们经常需要对两个版本的文档进行比对&#xff0c;比如合同修改、论文修订、报告更新等。手动逐字检查不仅耗时费力&#xff0c;还容易遗漏细节。 今天&#xff0c;我将带你使用 Python python-docx difflib 实现一个自动化 Word 文档对比工具…

从0开始搭建一个前端项目(vue + vite + typescript)

版本 node&#xff1a;v22.17.1 pnpm&#xff1a;v10.13.1 vue&#xff1a;^3.5.18 vite&#xff1a;^7.0.6 typescipt&#xff1a;~5.8.0脚手架初始化vue pnpm create vuelatest只选择&#xff1a; TypeScript, JSX 3. 用vscode打开创建的项目&#xff0c;并删除多余的代码esl…