想到括号问题,我最熟悉的是用stack来判断一个括号序列是否为valid。没错,这就是我对括号题,最初的认识。
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
思路:利用栈存最近访问的括号,如果遇到右括号,则到了judge时候。
class Solution {
public:
bool isValid(string s) {
stack<char> brackets;
int n=s.length();
if(n==0) return true;
if(n==1) return false;
int i=0;
for(i=0; i<n; i++){
if(s[i]=='(' || s[i]=='{' || s[i]=='[')
brackets.push(s[i]);
if(s[i]==')'){
if(brackets.empty()) return false;
char top=brackets.top();
brackets.pop();
if(top!='(') return false;
}
if(s[i]=='}'){
if(brackets.empty()) return false;
char top=brackets.top();
brackets.pop();
if(top!='{') return false;
}
if(s[i]==']'){
if(brackets.empty()) return false;
char top=brackets.top();
brackets.pop();
if(top!='[') return false;
}
}
if(brackets.empty()) return true;
return false;
}
};
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
思路:这题的关键点是左括号数必须等于右括号数,另外任何时候右括号数不超过左括号数。
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
generateParenthesis(res, "", n, n, n, 0);
return res;
}
void generateParenthesis(vector<string>& res, string s, int left, int right, int n, int lev){
if(lev==n*2){
res.push_back(s);
return;
}
if(left) generateParenthesis(res, s+'(', left-1, right, n, lev+1);
if(right>left && right) generateParenthesis(res, s+')', left, right-1, n, lev+1);
}
};
Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.
思路:我在这道题上犯二逼了,老是想着stack遍历,祈求能统计得到联系合理的括号对,但是老尝试失败,还折腾了一下午。。。后来,discussion里的小伙伴又拯救了我。从另一个思路出发,用stack存左括号,严格来说只存为匹配上的左括号(好像和stack遍历也没啥区别,到这里)。不同的是,这个stack不再是单纯存括号本身,而是存括号的index,可以通过index得到substring的长度(这应该是一种很普通的想法,可我咋就是没想到,猪~)
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> pstack; //栈存放unmatched左括号
int n=s.length();
if(n==0 || n==1) return 0;
int maxcount=0;
int lastofleft=0;
for(int i=0; i<n; i++){
if(s[i]=='(') pstack.push(i); //保存左括号的索引
else{
if(!pstack.empty()){
pstack.pop(); //求出上一个unmatched左括号到当前位置之前的括号个数
if(!pstack.empty()) //如果当前stack非空,则返回上一个左括号的位置
maxcount=max(maxcount, i-pstack.top());
else //如果当前stack为空,则求lastofleft到i之间的段的括号个数
maxcount=max(maxcount, i-lastofleft+1);
}
else lastofleft=i+1; //如果是右括号而且stack为空,这开始新的计数
}
}
return maxcount;
}
};
这个思路应该很眼熟才对,没错,就是就是maximal rectangle area,都是利用堆栈,更重要的是都是substring
也有其他小伙伴提出一种DP的解决方法,个人觉得不算是很大众的解法。这里也贴出来。利用动态规划的思想,用一维数值dp[]保存i到s末尾最大有效括号的长度
class Solution {
public:
int longestValidParentheses(string s) {
//利用动态规划的思想,用一维数值dp[]保存i到s末尾最大有效括号的长度
int n=s.length();
vector<int> dp(n, 0);
int maxcount=0;
for(int i=n-2; i>=0; i--){ //倒序更新dp的值
if(s[i]=='('){
int j=i+1+dp[i+1]; //上个未匹配到的位置
if(j<n && s[j]==')'){
dp[i]=dp[i+1]+2;
if(j+1<n)
dp[i]=dp[i]+dp[j+1];
}
}
maxcount=max(maxcount, dp[i]);
}
return maxcount;
}
};