leetcode:32 最长有效括号
题目:
给一个包含了'(' 和 ')'的字符串,求出其中最长有效括号的长度。
做题情况:自己做出来,但做了较长的时间。
思路:可以算得穷举法的时间复杂度为O(n^3)。虽然这题求的是最长的长度,但是用不了动态规划,因为无法找到一个合适的状态。考虑能不能在O(n)内实现,即遍历一次字符串。发现可以通过栈来做。具体方法如下:
对于当前字符,如果是"(",直接压入栈中。如果是")",要分以下几种情况讨论:
(1)如果当前栈为空,说明不存在与当前右括号配对的左括号,直接continue.
(2)如果当前栈大小为1:
a.如果栈顶元素是"(",则找到一个有效的括号序列,弹出栈顶元素,并压入这个序列的长度2;
b.如果栈顶元素是数字,说明不存在与当前右括号配对的左括号,且由于插入了一个右括号,之前得到的括号序列无法更长,需要弹出栈顶元素。
(3)如果当前栈的大小大于等于2:
弹出栈顶元素
a.如果是"(",则找到一个为2的有效序列,再检查栈顶元素,如果是数字,说明可以与前面找到的括号序列合并为一个更大的序列,与其相加后压入栈,否则直接将2压入栈;
b.如果是数字,由于当前的栈大小大于等于2,则下一个栈的元素一定是“(”,弹出后压入合并后的序列长度,压之前再检查,如果栈顶元素还是为数字,则再合并,再压入。
代码如下:
public class Solution { public int longestValidParentheses(String s) { int n = s.length(); Stack<Integer> stack = new Stack<Integer>(); int max = 0; for(int i=0;i<n;i++){ if(s.charAt(i)=='('){ stack.push(0); }else{ if(stack.size()==0){ continue; }else if(stack.size()==1){ if(stack.pop()==0){ stack.push(2); max = Math.max(max,2); } }else{ if(stack.peek()==0){ stack.pop(); int num = 2; if(stack.peek()!=0){ num += stack.pop(); } stack.push(num); max = Math.max(max,num); }else{ int temp = stack.pop(); stack.pop(); temp+=2; if(!stack.isEmpty()&&stack.peek()!=0){ temp += stack.pop(); } max = Math.max(max,temp); stack.push(temp); } } } } return max; } }