自己一开始不会做。。。
1:看到最长子串,首先想到的是DP?但是转移方程怎么列?没头绪啊(见方法一)
2:看到是括号匹配,想到用栈,但是暴力出每个子串,然后用栈来判断,O(n^3)的复杂度,很明显会超时,怎么做?(见方法二)
3:想到’(‘加一,’)‘减一,判断是否等于0来判断是否匹配,然而出现’)('怎么处理?(见方法三)
方法一:DP,时间空间都是O(n)
dp[i]表示以s[i]结尾的最长子串。
case1:当前字符是’(‘,必然不匹配。
case2:当前字符s[i]是’)’
---------------若前一个字符s[i-1]是’(‘,则,dp[i]=dp[i - 2] + 2;
---------------若s[i-1]是’)‘,若s[i-1]前面不匹配的第一个字符:s[i-1-dp[i-1]]是’(',dp[i]=dp[i-1]+2+dp[i-1-dp[i-1] - 1]。注意要加dp[i-1-dp[i-1] - 1]!!!
易错点:注意下标不能越界!!!
class Solution {
public:
int longestValidParentheses(string s) {
//DP
int n = s.size();
vector<int> dp(n);
int ans = 0;
for (int i = 0;i < n; ++i) {
if (s[i] == ')') {
if (i - 1 >= 0 && s[i - 1] == '(') {
dp[i] = i - 2 >= 0 ? dp[i - 2] + 2 : 2;
}
if (i - 1 >= 0 && s[i - 1] == ')') {
int index = i - 1 - dp[i - 1]; //s[i-1]左边第一个不匹配的位置
if (index >= 0 && s[index] == '(') {
dp[i] = index - 1 >= 0 ? dp[i - 1] + dp[index - 1] + 2 : dp[i - 1] + 2;
}
}
}
ans = max(ans, dp[i]);
}
return ans;
}
};
方法二:栈,时间空间都是O(n)
难点: 栈顶放左边第一个不匹配的字符的下标
具体为:
如果当前字符为’(‘,直接把下标入栈
如果当前字符为’)‘:如果栈顶是’(‘,出栈,并计算出匹配的长度更新ans;否则把下标入栈。
易错点:
1:更新的时候:当前下标减去栈顶不匹配的下标,而不是减去栈顶’('的下标!!!
2:为了方便边界判断,栈底先放一个-1
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> st;
st.push(-1);
int n = s.size(), ans = 0;
for (int i = 0; i < n; ++i) {
if (s[i] == '(') st.push(i);
else {
int index = st.top();
if (index != -1 && s[index] == '(') {
st.pop();
int tmp = i - st.top();
ans = max(tmp, ans);
}else {
st.push(i);
}
}
}
return ans;
}
};
方法三:双指针,时间O(n),空间O(1)
难点:
从左往右扫描,如果’)‘大于’(‘的数量,nums1 nums2都置为0!!!
具体为:
num1记录‘(’的个数,nums2记录‘ )‘的个数。
从左往右扫描,如果’)‘大于’(‘的数量,nums1 nums2都置为0,如果num1== nums2则匹配,更新ans
易错点:
上面这样会忽略’’(()"的情况,解决方案是,从右向左也扫描一遍,如果’(‘大于’)'的数量,nums1 nums2都置为0,如果num1==nums2则匹配,更新ans。
class Solution {
public:
int longestValidParentheses(string s) {
int nums1 = 0, nums2 = 0, n = s.size(), ans = 0; //分别记录左括号和右括号的数量
for (int i = 0; i < n; ++i) {
if (s[i] == '(') nums1++;
else nums2++;
if (nums1 == nums2) {
ans = max(ans, 2 * nums1);
}else if (nums2 > nums1) {
nums1 = nums2 = 0;
}
}
nums1 = nums2 = 0;
for (int i = n - 1; i >= 0; --i) {
if (s[i] == '(') nums1++;
else nums2++;
if (nums1 == nums2) {
ans = max(ans, 2 * nums1);
}else if (nums2 < nums1) {
nums1 = nums2 = 0;
}
}
return ans;
}
};