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

  For "(()", the longest valid parentheses substring is "()", which has length = 2.

  Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.

拿到题目,哎呀,这不是典型的动态规划嘛,然后刷刷开始coding。这道题确实可以用动态规划,但是复杂度就上去了,事实证明也没法通过大集合的测试。不过还是可以当一个DP的练习。如果你比较忙,直接看解法二吧。

用longestValid[i][j]表示从S串中的字符i到j的最长well-formed表达式的长度;isValid[i][j]表示从i到j是否是一个valid的表达式。

如何判断longestValid[i][j]的取值呢?有下面几种情况:

假定有一个maxlength变量。

1. 如果i='(' 并且 j=')',

  a. 如果j = i+1,那这是一个valid的表达式;

b. 如果isValid[i+1][j-1]为真,那这也是一个valid表达式;

  c. 对所有在i到j之间的k,如果isValid[i,k]&&isValid[k+1,j]为真,那么这是一个valid表达式,这三种情况maxlength都是i到j的距离;

  d.其他情况,maxlength = longestValid[i][j-1]和 longestValid[i+1][j]比较大的那个。

2. 如果i='(' 并且 j='(', maxlength等于longestValid[i][j-1]。

3. 如果i=')' 并且 j=')', maxlength等于longestValid[i+1][j]。

4. 如果i=')‘ 并且 j='(', maxlength等于longestValid[i-1][j-1].

判断完成后,longestValid[i][j]赋值于maxlength。

下面是代码,是不是很复杂很想给博客君一巴掌。

解法一:

 private static int longestValidParentheses(String s) {
// Start typing your Java solution below
// DO NOT write main() function
if(s.length() == 0) return 0;
boolean[][] isValid = new boolean[s.length()][];//isValid[i][j] is true when from i to j, this is a valid parentheses expression
int[][] longestValid = new int[s.length()][];//the longest length of valid expression between i and j
for(int i = 0; i < s.length();i++){
isValid[i] = new boolean[s.length()];
longestValid[i] = new int[s.length()];
}
for(int j = 1; j < s.length();j++){
for(int i = j - 1; i >=0;i--){
int left = s.charAt(i);
int right = s.charAt(j);
int maxLength = 0;
if(left == '(' && right ==')'){
if(i + 1 == j) {
isValid[i][j] = true;
if(maxLength < 2) maxLength = 2;
}else {
if(isValid[i+1][j-1]){
isValid[i][j] = true;
if(maxLength < j - i + 1) maxLength = j - i + 1;
}else if(isValid[i][i+1] && isValid[j-1][j] &&
(isValid[i + 2][j - 2] || j - i == 3)){
isValid[i][j]=true;
if(maxLength < j - i + 1) maxLength = j - i + 1;
}else {
maxLength = Math.max(longestValid[i][j-1], longestValid[i+1][j]);
for(int k = i + 1; k < j;k++){
if(isValid[i][k] && isValid[k + 1][j]) {
maxLength = j - i + 1;
isValid[i][j]=true;
break;
}
}
}
}
}else {
if(left == '(' && right == '('
&& longestValid[i][j-1] > maxLength) maxLength = longestValid[i][j-1];
if(left == ')' && right == ')'
&& longestValid[i+1][j] > maxLength)maxLength = longestValid[i+1][j];
if(left ==')' && right == '('
&& longestValid[i+1][j-1] > maxLength){
maxLength = longestValid[i+1][j-1];
}
}
longestValid[i][j] = maxLength;
}
}
return longestValid[0][s.length()-1];
}

plus,这是O(n3)的。。。。“该吃药了。。亲”。如期望的,该解法在大集合的时候超时。

解法二:来自leetcode讨论组的写法。本来人有O(n)的解法,被楼主活生生地卖弄成了O(n3)。楼主真想挖个坑把自己埋了!!!

大家首先看,这个解法里面的stack,不是用来存左右括号的。人是来存左括号的index。本来么,右括号也不用存。遍历S。遇到'(',放入lefts。如果遇到')',如果lefts是空,说明这是一个无法匹配的')',记录下last。last里面存放的其实是最后一个无法匹配的')'。为啥要保存这个值呢?主要是为了计算后面完整的表达式的长度。可以这样理解: “所有无法匹配的')'”的index其实都是各个group的分界点。

 public static int longestValidParentheses2(String s) {
int maxLen = 0, last = -1;
Stack<Integer> lefts = new Stack<Integer>();
for (int i=0; i<s.length(); ++i) {
if (s.charAt(i)=='(') {
lefts.push(i);
} else {
if (lefts.isEmpty()) {
// no matching left
last = i;
} else {
// find a matching pair
lefts.pop();
if (lefts.isEmpty()) {//有一个完整的valid的group。计算该group的长度
maxLen = Math.max(maxLen, i-last);
} else {
//栈内还有‘(',一个最外层完整的group还没有匹配完成,
//但是通过查询下一个即将匹配还未匹配的"("的index来更新maxLen。
maxLen = Math.max(maxLen, i-lefts.peek());
}
}
}
}
return maxLen;
}

总结下:

DP不是万能的。注意发现问题的本质。不过这个确实要靠足够的练习。解法二的代码确实很简洁,但是并不是人人都能想到的。

LeetCode 笔记系列八 Longest Valid Parentheses [lich你又想多了]的更多相关文章

  1. leetcode第31题--Longest Valid Parentheses

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  2. leetcode解题报告 32. Longest Valid Parentheses 用stack的解法

    第一道被我AC的hard题!菜鸡难免激动一下,不要鄙视.. Given a string containing just the characters '(' and ')', find the le ...

  3. LeetCode (32) Longest Valid Parentheses

    题目 Given a string containing just the characters '(' and ')', find the length of the longest valid ( ...

  4. leetcode解题报告 32. Longest Valid Parentheses 动态规划DP解

    dp[i]表示以s[i]结尾的完全匹配的最大字符串的长度. dp[] = ; ; 开始递推 s[i] = ')' 的情况 先想到了两种情况: 1.s[i-1] = '(' 相邻匹配 这种情况下,dp ...

  5. 【leetcode刷题笔记】Longest Valid Parentheses

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  6. 【一天一道LeetCode】#32. Longest Valid Parentheses

    一天一道LeetCode系列 (一)题目 Given a string containing just the characters '(' and ')', find the length of t ...

  7. [LeetCode] Longest Valid Parentheses 最长有效括号

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  8. Java for LeetCode 032 Longest Valid Parentheses

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  9. [LeetCode] Longest Valid Parentheses 解题思路

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

随机推荐

  1. hibernate中一对一映射

    一.hibernate中一对一映射有两种 1 主键方式,一张表的主键是通过另一张表的主键生成的 2 外键方式,一张表添加外键引用另一张表的主键,并添加唯一unique约束 二.下面进行简单例子,用户和 ...

  2. WCF实现RESTFul Web Service

    共同学习了前面一些概念,终于开始正题了哈.RESTful的Web Service调用直观,返回的内容容易解析.这里先会描述一个简单的场景--Web Service提供一个方法来搜索个人信息,传入人名, ...

  3. JVM基础学习之基本概念、可见性与同步

    开发高性能并发应用不是一件容易的事情.这类应用的例子包括高性能Web服务器.游戏服务器和搜索引擎爬虫等.这样的应用可能需要同时处理成千上万个请求.对于这样的应用,一般采用多线程或事件驱动的 架构 .对 ...

  4. 内存对齐与ANSI C中struct型数据的内存布局

    当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将如何在内存中放置这些字段?ANSI C对结构体的内存布局有什么要求?而我们的程序又能否依赖这种布局?这些问题或许对不 ...

  5. LoadRunner “add measurements”(添加度量)菜单问题

    HP LoadRunner 11版本  配置

  6. MySQL编码问题集合

    1.以root用户的身份登录,查看编码设置 mysql> SHOW VARIABLES LIKE 'character%'; +--------------------------+------ ...

  7. mouseover mouseenter mouseout mouseleave

    mouseover与mouseenter 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件. 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件. mouseou ...

  8. 跟着百度学PHP[13]-文件上传

    PS:上传的时候一定要用POST方法,GET方法不行. 文件上传的entype要改成“mutilpart/form-data”这个编码 <html> <form action=&qu ...

  9. 记一次安装多版本php的四个雷区,你踩着了吗

    记一次安装多版本php的四个雷区,你踩着了吗   技术小疯子关注3人评论740人阅读2018-06-29 15:00:30   记一次安装多版本的php的四个雷区,你踩着了吗 需求:公司需要在同一台服 ...

  10. Entity Framework(六):数据迁移

    在前面的几篇文章中,简单的介绍了如何使用Entity Framework的Code First模式创建数据库,但是,在前面的几篇文章中,我们都是通过使用数据库初始化策略来做,也就是每次先删除数据库然后 ...