算法题之最长有效括号的长度问题
问题描述
思路分析
代码实现
public int longestValidParentheses(String s) {
if (s == null || s.length() <= 1) {
return 0;
}
//定义一个栈
Stack<Integer> stack = new Stack<>();
int len = s.length();
//定义一个maxLen
int maxLen = 0;
//先给栈空间压入一个初始值-1:由于一个有效括号为2个长度,保证判断括号的长度
stack.push(-1);
for (int i = 0; i < len; i++) {
char val = s.charAt(i);
//如果当前字符为'(':则直接将其进行压栈处理
if (val == '(') {
stack.push(i);
}else {//如果添加的是')',则取出栈顶元素,判断当前栈是否为空,若为空,则直接将i进行入栈处理
stack.pop();//出栈元素
if (stack.empty()) {
stack.push(i);
}else {
//maxLen为之前maxLen和i - stack.peek()的值的大小
maxLen = Math.max(maxLen,i - stack.peek());
}
}
}
return maxLen;
}
代码实现
//动态规划进行求解
public int longestValidParentheses(String s) {
//如果s为null或者长度小等于1,则直接返回0
if (s == null || s.length() <= 1) {
return 0;
}
int len = s.length();
char[] sArr = s.toCharArray();
int[] dp = new int[len];//默认初始化为0
//定义一个maxLength:存储最长有效括号的长度值
int maxLength = 0;
//遍历数组
for (int i = 1; i < len; i++) {
if (sArr[i] == ')') {//如果sArr[i]为')'
if (sArr[i - 1] == '(') {//如果sArr[i - 1] == '('
if (i - 2 >= 0) {//判断sArr[i - 2]是否存在
dp[i] = dp[i - 2] + 2;
}else {
dp[i] = 2;
}
}else {//如果sArr[i - 1] == ')'
if (i - dp[i - 1] - 1 >= 0) {//判断sArr[i - dp[i - 1] -1]是否存在,不存在,则说明不匹配,将dp[i] = 0(默认为0)
if (sArr[i - dp[i - 1] - 1] == '(') {
if (i - dp[i - 1] - 2 >= 0) {//判断sArr[i - dp[i - 1] -2]是否存在
dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2;
}else {
dp[i] = dp[i - 1] + 2;
}
}
}
}
}
//如果sArr[i] = '(':则肯定无法构成有效括号,直接将dp[i] = 0(默认为0)
//每一次计算完dp[i]的值,和maxLength进行比较,更新maxLength的值
maxLength = Math.max(maxLength,dp[i]);
}
//for遍历结束,返回maxLength的值
return maxLength;
}
代码实现
//方法2:双指针完成.贪心算法实现
//第一次遍历字符串:只考虑右括号比左括号少的情况
//第二次遍历字符串:只考虑左括号比右括号少的情况
//两种遍历结果的结合即完成了所有情况的遍历统计,以完成有效括号子串的最长长度的求解
public int longestValidParentheses(String s) {
//首先判断s字符串是否为null或者s的长度是否小于等于1:如果满足要求,则直接返回0
if (s == null || s.length() <= 1) {
return 0;
}
//定义两个指针left和right
int left = 0;
int right = 0;
int maxLength = 0;//初始化最长有效括号子串长度为0
//进行第一次遍历
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
left++;
}else {//右括号
right++;
}
if (left == right) {
maxLength = Math.max(maxLength,2 * right);
}else if (right > left) {
left = right = 0;//剔除掉")(())"这种先右括号后左括号的情况:贪心地只考虑右括号比左括号少的情况
}
}
//重置left和right指针的值
left = right = 0;
//进行第二次遍历(反向遍历)
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '(') {
left++;
}else {//右括号
right++;
}
if (left == right) {
maxLength = Math.max(maxLength,2 * left);
}else if (left > right) {
left = right = 0;//剔除掉"(())("这种先右后左情况:贪心地只考虑左括号比右括号少的情况
}
}
//两次遍历:正序遍历和反序遍历结束以后
return maxLength;
}