题目
思路与算法
-
其实这几天不是偷懒断了写,是每天复习一阵子累的慌,挑简单的做了几个,属实没什么需要记录的,都是很简单的暴力,比如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) |