LeetCode Week14: Longest Valid Parentheses
来源:互联网 发布:淘宝美工常用尺寸 编辑:程序博客网 时间:2024/06/06 19:27
这周实现的还是Dynamic Programming的代码,这里选择一道比较经典的题目Longest Valid Parentheses来完成题解。
题目
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.
我的分析
刚开始拿到这个问题的时候,犯了一个错,就是认为是找有效的()对的长度,然后就想直接用栈来解决,结果后来提交的时候,有一个case是”()(()”,如果光按照匹配的方法,长度会是4,但是Expected Output = 2,这说明只有一对(),也就是说,这道题是要找的最长连续()。
考虑到这个情况,这个题我用了两种方法,两个方法的分析分别如下:
1、stack方法
因为做括号匹配的时候,最开始就是想到用栈来解决,但是这个问题中需要求解的是最长连续(),那么使用栈的时候,就需要考虑当前栈中元素的位置,也就是说,我会设定一个Pair的结构体,其中包括了当前元素的位置idx(int类型)及元素的值(char类型)s。
假设现在需要判断的序列是”()(()”,那么我们的操作如下:
- 如果当前元素是’(‘,那么直接将pair对(idx,’)’)放入栈中;
如果当前元素是’)’,那么需要依据当前栈的内容来判断要做什么操作,假设现在遍历到序列的最后一个元素,也就是’)’:
- 当前栈为空,那么可以把右扩号也放入栈中,这是为了帮助后面计算长度;
- 当前栈不为空, 那么可以组成一对(),同时需要把栈顶的’(‘抛出栈。但是抛出栈之后,新的问题又出现了:这一对()之前还有没有连续的()对,我应该怎么来更新现在的最长的连续配对()?这个问题的解决就可以看现在的栈的状态来判断了。如果把配对的’(‘元素pop出栈后,栈为空,那么表示之前进栈的元素都已经跟组成了()对,并且当前这一对与前面的()对是连续,那么最长的()长度就应该变为当前序列的长度;如果此时栈的状态不为空,那么这一对()跟前面可能已经形成的()对就不连续了,那么就应该判断,现有的()的长度就是i-top().idx(这里并不是直接判断为2是因为存在(())的情况);
- 之后可以判断是之前的长度更大,还是现在的()对更大,来动态更新最长()对的长度。
2、动态规划法
动态规划的过程就是把一个大问题划分成多个子问题来求解,这题是利用一个逆向思考的过程,思路是填充一个长度同样是length的数组dp,其中dp[i]表示从i到最后一为元素可以形成的最长的()的长度,从倒数第二个元素开始遍历(因为最后一个元素能形成的()对当然是0),如果当前元素是’(‘,那么填充这个数组的过程如下:
看第i+1+dp[i+1]个元素是否是’)’,如果是’)’,那么就可以组成一对’)’;这里使用dp[i+1]的原因是,存在(())的情况,如果遍历到’(‘,那么要去找从它数下去的第3个元素来判断(因为内部有一对()要跳过它们),而对于内部的(),我们是可以很容易判断出当遍历到左边的’(‘时,可以形成的最长的()对的长度就是2,那么此时应该去找j = i+1+dp[i+1]位置,即跳过下一个位置能形成的最长()长度之后的位置的值来判断是否是’)’;
当我们判断有一对合法的()时,我们还要看其后面的元素是否能与这一对形成一个连续的()对,如果’)’后面的元素的dp[j+1]不为0,表示后面也能形成连续的()对,当然dp[j+1]为0时就表明当前的这一对()与后面可能会有的连续()对是分开的。所以状态转移方程可以写作:
dp[i]=dp[i+1]+2+dp[j+1],j+1<s.length() 。
代码
1、直接使用栈的方法分析得到的代码如下:
struct Pair{ int idx; char s; Pair(int i,char j):idx(i),s(j){}};class Solution {public: int longestValidParentheses(string s) { stack<Pair>rec; int maxlen = 0; for(int i = 0; i < s.size();i++){ // 如果是(,那么直接push进栈 if(s[i] == '(') rec.push(Pair(i,'(')); else if(s[i] == ')'){ int cur = 0;// 现在的最长连续对 // 栈里面有元素可以匹配成一对() if(!rec.empty() && rec.top().s == '(') { rec.pop(); cur = 0; // 如果这时栈已经清空,那么这一次的()的长度要纳入前面的长度计算中 // 因为前面也有连续的()对 if(rec.empty()) cur = i+1; else // 栈未清空,前面残留有元素 // 说明这一对()与前面的()不连续,这时的长度只能是2 cur = i - rec.top().idx; } else{ rec.push(Pair(i,')')); } maxlen = max(maxlen,cur); } } return maxlen; }};
2、 使用动态规划分析得到的代码如下:
class Solution {public: int longestValidParentheses(string s) { int len = s.length(); vector<int>dp(len,0); int maxlen = 0; for(int i = len-2; i >=0; i--){ if(s[i] == '('){ // 看下一个元素是否是')' int idx = i+1+dp[i+1]; // 考虑到(())的情况 if(idx < len && s[idx] == ')') // 如果下一个元素是')',那么就可以组成一对() // 之后判断能够与后面的元素组成多长的连续() dp[i] = (idx+1 < len)?2+dp[idx+1]+dp[i+1]:2+dp[i+1]; } maxlen = max(dp[i],maxlen); } return maxlen; }};
- LeetCode Week14: Longest Valid Parentheses
- LeetCode: Longest Valid Parentheses
- LeetCode Longest Valid Parentheses
- LeetCode: Longest Valid Parentheses
- [Leetcode] Longest Valid Parentheses
- [leetcode]longest Valid Parentheses(!!)
- [Leetcode] Longest Valid Parentheses
- leetcode Longest Valid Parentheses
- 【leetcode】Longest Valid Parentheses
- [LeetCode]Longest Valid Parentheses
- [leetcode] Longest Valid Parentheses
- LeetCode-Longest Valid Parentheses
- [LeetCode] Longest Valid Parentheses
- LeetCode:Longest Valid Parentheses
- Leetcode: Longest Valid Parentheses
- Leetcode:Longest Valid Parentheses
- leetcode Longest Valid Parentheses
- leetcode Longest Valid Parentheses
- Dataadapter.Fill用法
- 斜率优化
- 下载chromium源码gclient代理设置 git代理设置
- Financial Management
- Python爬虫】安装 pyQuery 遇到的坑 Could not find function xmlCheckVersion in library libxml2. Is libxml2 inst
- LeetCode Week14: Longest Valid Parentheses
- 继承接口与实现接口的理解
- Verilog实现整数与小数部分的二进制转化为十进制
- 02-线性结构3 Reversing Linked List (25分)
- Java多线程基础详解
- JSTL
- [Linux]How to mix C and C++ 混合编译
- 给微赞程序富文本编辑器加上传附件功能
- json格式数据解析