力扣32(java)-最长有效括号(困难)
题目:
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
提示:
0 <= s.length <= 3 * 104
s[i] 为 '(' 或 ')'
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
一、栈
参照@笨猪爆破组 大佬的题解
由于该题需要求的是最长有效括号的子串长度,那么栈中不需要存放左括号,而是存放左括号的下标。当遇到右括号时,就弹出栈顶的左括号索引,然后就更新有效长度 = 当前右括号的索引 - 栈顶左括号的索引 + 1,在更新一下最大有效长度

但是当在索引6遇到右括号时,此时栈为空,找不到与之匹配的左括号了,这时前面索引5计算的长度为4,但是实际最大长度为6,这时不知该如何继续计算...
所以就需要在最开始的时候栈里设置一个“参照物”为-1,计算有效长度 = 当前右括号的索引 - 出栈后新的栈顶索引,在后面栈为空时遇到右括号,就将右括号的索引作为新的参照物压入栈中。

前面步骤省略
当遇到索引5时,有效长度为= 5 - (-1) = 6;
当遇到索引6时,就会将栈顶元素 -1 弹出,栈为空,将6压栈;
当遇到索引7时,7入栈;
当遇到索引8时,7出栈,有效长度= 8 - 6 = 2,更新最大长度仍为6;
当遇到索引9时,弹出栈顶元素6,栈为空,将9压栈;
当遇到索引10时,10入栈;
当遇到索引11时,10出栈,有效长度 = 11 - 9 = 2,更新最大长度仍为6;
遍历完毕,返回最大长度6。
代码:
1 class Solution {
2 public int longestValidParentheses(String s) {
3 int n = s.length();
4 Deque<Integer> stack = new ArrayDeque<>();
5 //最先让-1入栈作为参照物
6 stack.addLast(-1);
7 int max = 0;
8 for(int i = 0; i < n; i++){
9 char c = s.charAt(i);
10 if(c == '('){
11 stack.addLast(i);
12 }else{
13 stack.pollLast();
14 if(stack.isEmpty()){
15 //栈为空就把右括号索引入栈,作为新的参照物
16 stack.addLast(i);
17 }else{
18 max = Math.max(max,i - stack.peekLast());
19 }
20 }
21 }
22 return max;
23 }
24 }

二、动态规划(不好理解)
定义dp[i] : 以s[i]结尾的最长有效子串的长度。
子串的末位s[i] 要么是 '(',要么是 ')',下面分情况讨论:
1.s[i]是 '(',以左括号结尾一定不是有效子串,即 dp[i] = 0;
2.s[i]是 ')',这时候就需要考虑前一个子串的末位 s[i-1]:
- 如果 s[i-1] 是 '(',刚好与 s[i] 组成一对,最长有效长度至少也得为2,这时候又需要考虑再前面一个子串末位 s[i-2]:
- 如果 s[i-2]不存在,则有效长度为2,即 dp[i] = 2;
- 如果s[i-2]存在,则需要加上以s[i-2]结尾的有效长度,即dp[i] = dp[i-2] + 2;

- 如果 s[i-1]是 ')',以s[i-1]结尾的最长有效长度为 dp[i-1],这时候就需要看第 i -dp[i-1] - 1这个位置的字符即 s[i-dp[i-1]-1]:
- 如果 s[i-dp[i-1]-1]处的字符不存在或者为 ')',就不能与s[i]处的 ')'配对,即dp[i] = 0;
- 如果 s[i-dp[i-1]-1]处的字符为 '(',与s[i]处的 ')'配对,这时候dp[i] 至少也得为dp[i-1] +2,这时候就看s[i-dp[i-1]-1-1] (s[i-dp[i-1]-2])是否存在:
- s[i-dp[i-1]-2] 存在,dp[i] = dp[i-dp[i-1] -2] + dp[i-1] + 2;
- s[i-dp[i-1]-2]不存在,dp[i] = dp[i-1] + 2;

代码:
1 class Solution {
2 public int longestValidParentheses(String s) {
3 int n = s.length();
4 int ans = 0;
5 int[] dp = new int[n];
6 for(int i = 1; i < n; i++){
7 if(s.charAt(i) == ')'){
8 if(s.charAt(i-1) == '('){
9 dp[i] = (i >= 2) ? dp[i-2]+2 : 2;
10 }else if(i - dp[i-1] > 0 && s.charAt(i- dp[i-1] -1)== '('){
11 //保证第i - dp[i-1]这个位置之前还有字符且前一个字符还必须为左括号
12 dp[i] = dp[i-1] + 2 + (i-dp[i-1] - 2 >= 0 ? dp[i-dp[i-1] -2] : 0);
13 }
14 ans = Math.max(ans, dp[i]);
15 }
16 }
17 return ans;
18 }
19 }

力扣32(java)-最长有效括号(困难)的更多相关文章
- 32、最长有效括号 | 算法(leetode,附思维导图 + 全部解法)300题
零 标题:算法(leetode,附思维导图 + 全部解法)300题之(32)最长有效括号 一 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: // 方案1 "滑动窗 ...
- 【LeetCode 32】最长有效括号
题目链接 [题解] 设dp[i]表示以第i个字符结尾的最长有效括号的长度. 显然只要考虑s[i]==')'的情况 则如果s[i-1]=='(',则dp[i] = dp[i-2]+2; 如果s[i-1] ...
- Leetcode(32)-最长有效括号
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 示例 1: 输入: "(()" 输出: 2 解释: 最长有效括号子串为 "()&quo ...
- 力扣(LeetCode)长按键入 个人题解
你的朋友正在使用键盘输入他的名字 name.偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次. 你将会检查键盘输入的字符 typed.如果它对应的可能是你的朋友的名字(其中一 ...
- Java实现 LeetCode 32 最长有效括号
32. 最长有效括号 给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 示例 1: 输入: "(()" 输出: 2 解释: 最长有效括号子串为 & ...
- LeetCode 32. 最长有效括号(Longest Valid Parentheses) 31
32. 最长有效括号 32. Longest Valid Parentheses 题目描述 给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 每日一算法2019/6/ ...
- LeetCode--032--最长有效括号(java)
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 示例 1: 输入: "(()" 输出: 2 解释: 最长有效括号子串为 "()&quo ...
- 【LeetCode-面试算法经典-Java实现】【032-Longest Valid Parentheses(最长有效括号)】
[032-Longest Valid Parentheses(最长有效括号)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a string contai ...
- C++双指针滑动和利用Vector实现无重复字符的最长子串—力扣算法
题目: 力扣原题链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 给定一个字符串, ...
- [LeetCode] 32. Longest Valid Parentheses 最长有效括号
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
随机推荐
- C++数值类型与string、CString之间的转换
目录 数值范围 数值类型与string互相转换 数值类型转换为string 使用函数模板+ostringstream 使用标准库函数std::to_string() string转换为数值类型 使用函 ...
- Android IjkPlayer解决RTSP延时300ms左右
简介 在上一篇<ijkplayer编译-RTSP>中介绍了,ijkplayer如何进行编译成so库的,以及如何开启rtsp.那么实际在使用的时候会发现延迟不是一般的大. 现在来介绍一下如何 ...
- 三维模型3DTile格式轻量化纹理压缩技术方法浅析
三维模型3DTile格式轻量化纹理压缩技术方法浅析 三维模型的纹理数据通常占据了模型数据的大部分,因此纹理压缩对于3DTile格式轻量化压缩来说至关重要.下面将详细分析几种主要的纹理压缩技术方法: D ...
- 基于proteus的数字电路设计
基于proteus的数字电路设计 1.实验原理 proteus的数字电路仿真能力还是比较强大的.这里总结一下proteus的几个基本操作以备后用.大致包括74hc系列的使用.常用调试设备.仿真开关.器 ...
- linux系统centos7.9如何安装nginx
1.官网下载nginx nginx官网:https://nginx.org/ 选择稳定版进行下载,也可以下载老版本,下载成功后上传到服务器. 2.使用wget下载 访问nginx官网,在下载页面鼠标右 ...
- KingbaseES V8R6 等待事件之LWLock Buffer_IO
等待事件含义 当进程同时尝试访问相同页面时,等待其他进程完成其输入/输出(I/O)操作时,会发生LWLock:BufferIO等待事件.其目的是将同一页读取到共享缓冲区中. 每个共享缓冲区都有一个与L ...
- 【Java】使用位运算完成数组中两个变量交换位置
1 /** 2 * 3 */ 4 package com.raliable.chapter_0; 5 /** 6 * @author : Administrator 7 * @date :2022年4 ...
- 大数据hadoop Linux 相关常用命令行操作
bin/zkServer.sh start bin/zkServer.sh stop 启动Hadoop 1 hadoop102 sbin/start-dfs.sh 2 hadoop103 sbin/s ...
- 8 JavaScript函数
8 JavaScript函数 在JS中声明函数和python差不多. 也要有一个关键字顶在前面. python是def, 到了JS里换成了function, 只不过在JS中没有像python那么死板, ...
- Android NDK之使用 arm-v7a 汇编实现两数之和
Android NDK之使用 arm-v7a 汇编实现两数之和 关键词: NDK armv7a WebRTC arm汇编 CMake 最近适配对讲程序,在webrtc的库编译的过程中,发现其为arm的 ...