leecode 32. Longest Valid Parentheses

leecode 32. Longest Valid Parentheses

题目大意

给出一个只含有’(‘和’)’的字符串,求这个字符串里面最长的合理括号组合字符串的长度。

解题思路

一开始觉得会跟判断合法括号字符串一样,用一个stack就能解决,但是发现行不通,因为像”()(()”这种情况,没办法将前后的”()”分开。结果只是154 / 229 test cases passed.

代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        int maxLen = 0, curLen = 0, curInd = 0;
        stack<char> parentheseStack;
        while (curInd < s.length()) {
            if (s[curInd] == '(') {
                parentheseStack.push('(');
                curInd++;
            } else if (s[curInd] == ')' && !parentheseStack.empty() && parentheseStack.top() == '(') {
                curLen += 2;
                parentheseStack.pop();
                curInd++;
            } else {
                maxLen = max(maxLen, curLen);
                curLen = 0;
                while (!parentheseStack.empty()) {
                    parentheseStack.pop();
                }
                curInd++;
                continue;
            }
        }
        maxLen = max(maxLen, curLen);
        return maxLen;
    }
};

看到一个用stack的O(N)的方法,记录一下

The workflow of the solution is as below.
1. Scan the string from beginning to end.
2. If current character is ‘(‘,push its index to the stack. If current character is ‘)’ and thecharacter at the index of the top of stack is ‘(‘, we just find a matching pair so pop from the stack. Otherwise, we push the index of ‘)’ to the stack.
3. After the scan is done, the stack will only contain the indices of characters which cannot be matched. Then let’s use the opposite side - substring between adjacent indices should be valid parentheses.
4. If the stack is empty, the whole input string is valid. Otherwise, we can scan the stack to get longest valid substring as described in step 3.

改用动态规划,用二维的状态表保存字符串的合法情况,statusTable[i][j]代表的是s[i..j]的合法情况,递推公式比较直观。

代码

const int stringSize = int(s.length());
        if (stringSize == 0) {
            return 0;
        }
        bool statusTable[stringSize][stringSize];
        for (int i = 1; i < stringSize; i++) {
            for (int j = 0; j < stringSize - i; j++) {
                if (i == 1) {
                    statusTable[j][j + i] = s[j] == '(' && s[j + i] == ')';
                } else if (i == 2) {
                    statusTable[j][j + i] = false;
                } else {
                    statusTable[j][j + i] = statusTable[j + 1][j + i - 1] && s[j] == '(' && s[i] == ')';
                }
            }
        }
        int maxLen = 0;
        for (int i = 1; i < stringSize; i++) {
            for (int j = 0; j < stringSize - i; j++) {
                if (statusTable[j][j + i]) {
                    maxLen = max(maxLen, i + 1);
                }
            }
        }
        return maxLen;
    }

当遇到大小为12477的字符串的时候会runtime error,以为无法在类方法里面分一个大小为12477^2的bool数组。改为动态分配内存。不过仍旧超时,思路太朴素了。

int longestValidParentheses(string s) {
        const int stringSize = int(s.length());
        if (stringSize == 0) {
            return 0;
        }
        bool **statusTable = new bool*[stringSize];
        for (int i = 0; i < stringSize; i++) {
            statusTable[i] = new bool[stringSize];
        }
        for (int i = 1; i < stringSize; i++) {
            for (int j = 0; j < stringSize - i; j++) {
                if (i == 1) {
                    statusTable[j][j + i] = s[j] == '(' && s[j + i] == ')';
                } else if (i == 2) {
                    statusTable[j][j + i] = false;
                } else {
                    statusTable[j][j + i] = false;
                    if (statusTable[j + 1][j + i - 1] && s[j] == '(' && s[j + i] == ')') {
                        statusTable[j][j + i] = true;
                    }
                    for (int k = j + 1; k + 1 < j + i; k++) {
                        if (statusTable[j][k] && statusTable[k + 1][j + i]) {
                            statusTable[j][j + i] = true;
                            break;
                        }
                    }
                }
            }
        }
        for (int i = 0; i < stringSize; i++) {
            for (int j = 0; j < stringSize; j++) {
                cout << statusTable[i][j] << " ";
            }
            cout << endl;
        }
        cout << endl;
        int maxLen = 0;
        for (int i = 1; i < stringSize; i++) {
            for (int j = 0; j < stringSize - i; j++) {
                if (statusTable[j][j + i]) {
                    maxLen = max(maxLen, i + 1);
                }
            }
        }
        return maxLen;
    }

换一个思路,直接用一个一维数组statusTable,statusTable[i]就代表是以s[i]为结束字符的字符串的最大合理长度。明显,任何以’(‘为结束的字符串都不可能是合法的,当s[i] == ‘(‘时,statusTable[i]=0;以’)’为结尾的字符串有可能是合法的,如果s[i-1] == ‘(‘,则statusTable[i]=statusTable[i-2]+2;如果s[i-1] == ‘)’,s[i-1]和s[i]就不可能凑成一对,那就要一个个往前推,做比较么,这时候可以利用statusTable[i-1],statusTable[i-1]记录以s[i]为结束字符的字符串的最大合理长度,如果s[i-statusTable[i-1]]==’(‘,就可以得到statusTable[i]=statusTable[i-1]+2,否则就是0。

And the DP idea is :

If s[i] is '(', set longest[i] to 0,because any string end with '(' cannot be a valid one.
Else if s[i] is ')'
    If s[i-1] is '(', longest[i] = longest[i-2] + 2
    Else if s[i-1] is ')' and s[i-longest[i-1]-1] == '(', longest[i] = longest[i-1] + 2 + longest[i-longest[i-1]-2]

实现代码

class Solution {
public:
    int longestValidParentheses(string s) {
        const int stringSize = int(s.length());
        //用一个一维的数组记录最大长度
        if (stringSize == 0) {
            return 0;
        }
        int maxLen = 0;
        int statusTable[stringSize];
        statusTable[0] = 0;
        for (int i = 1; i < stringSize; i++) {
            if (s[i] == '(') {
                statusTable[i] = 0;
            } else {
                int internalLen = statusTable[i - 1];
                if (s[i - internalLen - 1] == '(') {
                    if (i - internalLen - 2 >= 0) {
                        statusTable[i] = statusTable[i - internalLen - 2] + statusTable[i - 1] + 2;
                    } else {
                        statusTable[i] = statusTable[i - 1] + 2;
                    }
                    maxLen = max(statusTable[i], maxLen);
                } else {
                    statusTable[i] = 0;
                }
            }
        }
        for (int i = 0; i < stringSize; i++) {
            cout << statusTable[i] << " ";
        }
        cout << endl;
        return maxLen;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值