Leetcode_C++之678. Valid Parenthesis String(有效括号字符串)

题目名称

Valid Parenthesis String

题目描述

Given a string s containing only three types of characters: ‘(’, ‘)’ and ‘*’, return true if s is valid.

The following rules define a valid string:
Any left parenthesis ‘(’ must have a corresponding right parenthesis ‘)’.
Any right parenthesis ‘)’ must have a corresponding left parenthesis ‘(’.
Left parenthesis ‘(’ must go before the corresponding right parenthesis ‘)’.
‘*’ could be treated as a single right parenthesis ‘)’ or a single left parenthesis ‘(’ or an empty string “”.

Example 1:
Input: s = “()”
Output: true

Example 2:
Input: s = “(*)”
Output: true

Example 3:
Input: s = “(*))”
Output: true

Constraints:
1 <= s.length <= 100
s[i] is ‘(’, ‘)’ or ‘*’.

初试思路

1.存在一对括号的左边子串和右边子串即【(左边)右边】都是valid的,则整个字符串也valid,用递归实现。但是会TLE。
2.采用记忆法,空间换时间。因为在计算子串是否是valid时存在重复计算,所以可以将子串是否valid的结果存放在二维数组中。
3. 最佳方案:括号匹配:遇’(‘加一,遇’)'减一,注意处理负数情况。有星号’*‘,count是一个范围,用minCount记录最小count,maxCount记录最大count。

初试代码

// 我的代码1(会TLE)
class Solution {
public:
    bool checkValidString(string s) {
        return checkValidSubString(s, 0, s.size()-1);
    }
    bool checkValidSubString(string &s, int i, int j){
        if(i>j){
            return true;
        }
        if(s[i] == ')'){
            return false;
        }
        else if(s[i] == '*'){ // '*'当成空
            if(checkValidSubString(s, i+1, j)){
                return true;
            }
        }
        for(int k=i+1; k<=j; k++){
            if(s[k] == ')' || s[k] == '*'){ //’*‘当成’)‘
                if(checkValidSubString(s, i+1, k-1) && checkValidSubString(s, k+1, j)){
                    return true;
                }
            }                
        }
        return false;
    }
};


//我的代码2(空间换时间)
class Solution {
public:
    bool checkValidString(string s) {
        int **VALID; //0:没算过  1:算过且是true  -1:算过且是false
        bool res=true;
        VALID = new int *[size(s)];
        for (int i = 0; i < size(s); i++) {
            VALID[i] = new int [size(s)];
        }
        for(int i=0; i<size(s); i++){
            for(int j=0; j<size(s); j++){
                VALID[i][j] = 0;
            }
        }
        res = checkValidSubString(s, 0, s.size()-1, VALID);
        for (int i = 0; i < size(s); i++) {
            delete [] VALID[i];
        }
        delete []VALID;/*释放数组*/
        return res;

    }

    bool checkValidSubString(string &s, int i, int j, int ** VALID){
        if(i>j){
            return true;
        }
        if(VALID[i][j] != 0){//算过了
            return VALID[i][j] == 1;
        }
        if(s[i] == ')'){
            VALID[i][j] = -1;
            return false;
        }
        else if(s[i] == '*'){ // '*'当成空
            if(checkValidSubString(s, i+1, j, VALID)){
                VALID[i][j] = 1;
                return true;
            }
        }
        for(int k=i+1; k<=j; k++){
            if(s[k] == ')' || s[k] == '*'){
                if(checkValidSubString(s, i+1, k-1, VALID) && checkValidSubString(s, k+1, j, VALID)){
                    VALID[i][j] = 1;
                    return true;
                }
            }                
        }
        VALID[i][j] = -1;
        return false;
    }
};

//代码3(最优版本)
class Solution {
public:
    bool checkValidString(string s) {
        int minCount = 0;
        int maxCount = 0;
        for(int i=0; i<size(s); i++){
            if(s[i]=='('){
                minCount++;
                maxCount++;
            }
            if(s[i]==')'){
                minCount--;
                maxCount--;
            }
            if(s[i]=='*'){
                minCount--;
                maxCount++;
            }
            if(maxCount<0){
                return false;
            }
            if(minCount<0){
                minCount = 0;
            }
        }
        return minCount==0;
    
    }
};

学到了啥

注意二维数组的动态内存分配和释放;
注意分治思想的运用;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值