【力扣LeetCode】32 最长有效括号

2024-08-28 22:38

本文主要是介绍【力扣LeetCode】32 最长有效括号,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述(难度难)

给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”

示例 2:

输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”

链接

https://leetcode-cn.com/problems/longest-valid-parentheses/

思路

1、最暴力的方法,对每个子串检验是否满足要求,对子串检测参考第20题:
https://leetcode-cn.com/problems/valid-parentheses/
解答见另一篇博客:
https://blog.csdn.net/u013095333/article/details/90714399
这样做时间上肯定过不了。

2、动态规划,用dp[i][j]表示从ij的括号左括号比右括号多的数量,如果某一时刻为负数,即右括号比左括号多,则以i开头,长度大于j的子串均不可能有效。不过这个做法,可以过227/230个用例,对于一个字符串长度达到12477超过题目限制内存。
这里还有一个小细节,在分配dp数组的空间时,由于数组特别大,如果直接以局部变量的形式在栈上面分配,则编译无法通过,(使用变量给数组,则运行会失败)。需要在堆上分配二维数组。
在堆上分配二维数组参考:

  • https://www.cnblogs.com/yyxt/p/4268304.html
  • https://blog.csdn.net/lavorange/article/details/42879605

对于本题,leetcode内存限制,即使在堆上分配,程序运行没有问题,但是却过不了。

3、动态规划,改进dp,或者使用栈?见:https://leetcode-cn.com/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode/
动态规划较为复杂一点
使用栈比较好理解一些

4、我们利用两个计数器 leftright 。首先,我们从左到右遍历字符串,对于遇到的每个 (,我们增加 left 计算器,对于遇到的每个 ) ,我们增加 right 计数器。每当 left 计数器与 right 计数器相等时,我们计算当前有效字符串的长度,并且记录目前为止找到的最长子字符串。如果 right 计数器比 left 计数器大时,我们将 leftright 计数器同时变回 0

接下来,我们从右到左做一遍类似的工作。
非常高效,算法动画图见:https://leetcode-cn.com/problems/longest-valid-parentheses/solution/zui-chang-you-xiao-gua-hao-by-leetcode/

代码

第2种情况的代码,leetcode过不了:

class Solution {
public:int longestValidParentheses(string s) {int slen = s.length();if(slen == 0){return 0;}// 在堆上分配空间,会超过内存限制// 直接在栈上分配空间,会导致编译错误,栈上分配不了这么大的空间 // int dp[slen][slen];int **dp = NULL;dp = new int*[slen];for(int i = 0; i < slen; i++){dp[i] = new int[slen];}for(int i = 0; i < slen; i++){for(int j = 0; j < slen; j++){dp[i][j] = -2;}}for(int i = 0; i < slen; i++){if(s[i] == '('){dp[i][i] = 1;}if(s[i] == ')'){dp[i][i] = -1;}}for(int i = 1; i < slen; i++){ // 距离 for(int j = 0; j + i < slen; j++){if(dp[j][j+i-1] >= 0){if(s[j+i] == '('){dp[j][j+i] = dp[j][j+i-1] + 1;}if(s[j+i] == ')'){dp[j][j+i] = dp[j][j+i-1] - 1;}}}}int ans = 0;for(int i = 0; i < slen; i++){for(int j = i; j < slen; j++){// cout << i << " " << j << " " << dp[i][j] << endl;if(dp[i][j] == 0){if(ans < j-i){ans = j-i+1;}}}}return ans;}
};

第4种方案代码:

class Solution {
public:int longestValidParentheses(string s) {int slen = s.length();if(slen == 0){return 0;}int left = 0;int right = 0;int ans = 0;int ansTemp = 0;for(int i = 0; i < s.length(); i++){if(s[i] == '('){left++;}if(s[i] == ')'){right++;if(right > left){right = 0;left = 0;ansTemp = 0;continue;}}ansTemp++;if(left == right){if(ans < ansTemp){ans = ansTemp;}}}ansTemp = 0;left = 0;right = 0;for(int i = s.length() - 1; i >= 0; i--){if(s[i] == ')'){right++;}if(s[i] == '('){left++;if(right < left){right = 0;left = 0;ansTemp = 0;continue;}}ansTemp++;if(left == right){if(ans < ansTemp){ans = ansTemp;}}}return ans;}
};

这篇关于【力扣LeetCode】32 最长有效括号的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1116090

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

hihocoder1050 : 树中的最长路

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho得到了一棵二叉树玩具,这个玩具是由小球和木棍连接起来的,而在拆拼它的过程中,小Ho发现他不仅仅可以拼凑成一棵二叉树!还可以拼凑成一棵多叉树——好吧,其实就是更为平常的树而已。 但是不管怎么说,小Ho喜爱的玩具又升级换代了,于是他更加爱不释手(其实说起来小球和木棍有什么好玩的是吧= =)。小Ho手

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

POJ1631最长单调递增子序列

最长单调递增子序列 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokenizer;publ

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点