題目
思路與算法
-
其實這幾天不是偷懶斷了寫,是每天覆習一陣子累的慌,挑簡單的做了幾個,屬實沒什麼需要記錄的,都是很簡單的暴力,比如35:插入搜索位置,比如1365. 有多少小於當前數字的數字。
-
本題思路一上來想到的是棧,這類1對1的題,就是棧,碰見左括號入棧,碰見右括號出棧,最後要是棧不爲空,就說明無效字符串,棧爲空,則都匹配了,有效字符串,然後記得更新res結果就行。最後注意特殊情況的處理。
-
思路二:動態規劃,這類題的規律比較難找,我們看給的這倆示例:
這兩個示例說:已經匹配完成的,如果後面再跟一個(),那麼還是匹配的
回頭我們再看一個實例:
()()(())
你發現這個字符串也是匹配的,把前面的倆()()去掉,後面的(())也是匹配的。也就是說,如果遇到這樣的雙括號套環,甚至三四個括號套環,也是完全可以的。因此我們需要來找出這其中的狀態方程。
思路總結: -
只有一個()括號時:dp[i] = dp[i-2] + 2;
-碰到右括號套環時:先找內層括號對應的左括號的索引, -
則dp[i] = dp[i-1] + 2 + dp[i - 1 - dp[i-1] - 1]。
-
思路三
-
左右數左括號和右括號的數量,從左往右數一遍,從右往左再數一遍,更新條件:左->右時:右括號>左括號數量時,清零。同理,右->左時,右括號<左括號數量時,清零。
代碼實現
思路一:
package com.immunize.leetcode.longestValidParentheses;
import java.util.Stack;
public class Solution2 {
public int longestValidParentheses(String s) {
// 特殊情況處理
if (s == null) {
return 0;
}
// 定義使用的變量
int res = 0;
// 遍歷所有字符串,進行暴力,並挨個判斷是否爲有效括號,注意括號是成對出現的,因此注意遍歷技巧
for (int i = 0; i < s.length(); i++) {
for (int j = i + 2; j <= s.length(); j++) {
if (isValid(s.substring(i, j))) {
res = Math.max(res, j - i);
}
}
}
return res;
}
// 判斷該字符串是否有效
private static boolean isValid(String s) {
// 特殊情況處理
/*
* 碰到左括號,則入棧一個左括號,碰到一個右括號,則出棧一個左括號,結束時如果棧空,則該字符串 是有效的,若棧不爲空,則無效,
*/
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
stack.push('(');
} else if (!stack.empty() && s.charAt(i) == ')') {
stack.pop();
} else {
return false;
}
}
return stack.empty();
}
}
思路二:
package com.immunize.leetcode.longestValidParentheses;
/**
* ")()())"
*
* 只有一個右括號時:dp[i] = dp[i-2] + 2;
*
* 兩個右括號時:先找內層括號對應的左括號的索引,
*
* 假設兩個右括號的索引爲 i-1,i。則dp[i] = dp[i-1] + 2 + dp[i - 1 - dp[i-1] - 1]
*
* @author Mr IMMUNIZE
*
*/
public class Solution {
public int longestValidParentheses(String s) {
int maxans = 0;
int dp[] = new int[s.length()];
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == ')') {
if (s.charAt(i - 1) == '(') {
dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
} else if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == '(') {
dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;
}
maxans = Math.max(maxans, dp[i]);
}
}
return maxans;
}
}
思路三:
package com.immunize.leetcode.longestValidParentheses;
public class Solution3 {
public int longestValidParentheses(String s) {
int res = 0;
int left, right;
left = right = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
if (left < right) {
left = right = 0;
}
if (left == right) {
res = Math.max(res, left + right);
}
}
left = right = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
if (left > right) {
left = right = 0;
}
if (left == right) {
res = Math.max(res, left + right);
}
}
return res;
}
}
複雜度分析
思路 | 時間複雜度 | 空間複雜度 |
---|---|---|
一 | O(N²) | O(N) |
二 | O(N) | O(N) |
三 | O(N) | O(1) |