題目:
給一個包含了'(' 和 ')'的字符串,求出其中最長有效括號的長度。
做題情況:自己做出來,但做了較長的時間。
思路:可以算得窮舉法的時間復雜度為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; } }