Longest Valid Parentheses

Longest Valid Parentheses

题目

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"

分析

这道题的要求就是根据给出的只包含()字符串,然后求出最长的合法子串(即()能够匹配)。

解法一

我的做法是使用一个数组大小为字符串长度。遍历字符串,将(记为-1)记为1
然后遍历数组。数组的值如果为1,则向左寻找第一个值为-1的元素,然后将两者的值都置为0,表示相互匹配。
之后再次遍历数组,统计连续出现的0的个数。返回统计结果中最大的值。
但是这种解法的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

解法二

其实还有一种时间复杂度为 O ( n ) O(n) O(n)的解法。
具体解法是:
从左到右遍历字符串。记录(出现的次(left)数和)出现的次数(right)。当(出现的次数等于)出现的次数时,设置maxLength = maxLength > right* 2 ? maxLength : right * 2。当)出现的次数大于(出现的次数时,设置left = right = 0
遍历一遍之后,会漏掉(出现的次数大于),但是其子串匹配的数目大于maxLength的情况。例如:()(()()(),此时得到的结果为2
因此需要从右到左再次遍历字符串。现在时当(括号出现的次数大于)出现的次数时,设置left = right = 0,和上一次遍历相反。当(出现的次数和)出现的次数相同时,依旧设置maxLength = maxLength > right* 2 ? maxLength : left * 2
这样就可以得到正确的结果了。

代码如下

解法一代码

class Solution {
    public int longestValidParentheses(String s) {
        int max = 0;
        int[] arr = new int[s.length()];
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                arr[i] = -1;
            } else {
                arr[i] = 1;
            }
        }
        for (int i = 1; i < s.length(); i++) {
            if (arr[i] == 1) {
            	// 可以记录上一次左括号出现的位置以加快遍历,但这里没有
                int j = i;
                while (--j >= 0) {
                    if (arr[j] == -1) {
                        arr[i] = 0;
                        arr[j] = 0;
                        break;
                    } else if (arr[j] == 1) {
                        break;
                    }
                }
            }
        }
        int tempMax = 0;
        for (int i = 0; i < s.length(); i++) {
            if (arr[i] == 0) {
                tempMax++;
            } else {
                max = max > tempMax ? max : tempMax;
                tempMax = 0;
            }
        }
        max = max > tempMax ? max : tempMax;
        return max;
    }
}

解法二代码

class Solution {
    public int longestValidParentheses(String s) {
        int left = 0, right = 0, maxlength = 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 = 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;        
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值