【Leetcode】有效括号

20. 有效的括号(栈)

leetcode 20
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串。

思路: 因为有效括号字符串必须要相互匹配,从左向右遍历时不能存在当前位置之前右括号比左括号多的情况,栈可以辅助我们完成这一判断。

class Solution {
public:
    bool isValid(string s) {
        // 定义不同括号的配对关系
        unordered_map<char, char> map;
        map['('] = ')';
        map['['] = ']';
        map['{'] = '}';
        // 声明一个栈,用来储存左括号,并与新来的括号做比对
        stack<char> st;
        int i = 0;
        while(i < s.size()) {
            if(s[i] == '(' || s[i] == '[' || s[i] == '{') st.push(s[i]); // 左括号入栈
            else {
                if(!st.empty() && map[st.top()] == s[i]) st.pop(); // 右括号与栈顶左括号匹配,栈顶左括号出栈
                else return false; // 栈空时出现右括号 or 右括号与栈顶左括号不匹配,返回false
            }
            i++;
        }
        // 遍历完所有括号,如果栈空则是有效字符串返回true,否则返回false
        return st.empty() ? true : false; 
    }
};

22. 括号生成(dfs)

leetcode 22
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的括号组合。

思路: 因为题目要求生成所有可能的括号组合,所以想到可以使用dfs暴力搜索所有的可能性。同时需要注意为了保证生成的是有效括号,不能让当前字符串中的右括号数大于左括号数。

class Solution {
public:
    vector<string> ans;

    void dfs(string& res, int l, int r) {
        // 当左、右括号全部用完时,即生成了一个有效括号组合,加入ans,返回
        if(l == 0 && r == 0) {
            ans.push_back(res);
            return;
        }
        // 如果还有左括号剩余,则添加一个左括号
        if (l > 0) {
            res += '(';
            dfs(res, l - 1, r);
            res.erase(res.end() - 1); // 回退
        }
        // 如果剩余的右括号数大于剩余的左括号数,则添加一个右括号
        if (r > l) {
            res += ')';
            dfs(res, l, r - 1);
            res.erase(res.end() - 1); // 回退
        }
    }

    vector<string> generateParenthesis(int n) {
        // 声明一个存储可能组合的字符串
        string res;
        // 因为所有可能性都要被找出,所以dfs为void型函数,需要迭代各种可能性
        dfs(res, n, n);
        return ans;
    }
};

32. 最长有效括号(动态规划)

leetcode 32
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。

思路: 因为题目要求最长的包含有效括号的子串的长度,是一个最值问题,往往可以使用动态规划来解决。注意这里dp数组的含义:以第i个元素结尾的子串中最长的有效括号的长度为dp[i],而不是前i个元素的最长的有效括号的长度。

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.size();
        if(n < 2) return 0;
        // 声明dp数组,以第i个元素结尾的子串中最长的有效括号的长度为dp[i]
        int dp[n];
        memset(dp, 0, sizeof(dp));
        // 循环更新dp数组
        int maxx = 0;
        for(int i = 1; i < n; i++) {
            // 如果当前为左括号'('则以其结尾的子串必然不包含有效括号,dp[i]依旧为0
            if(s[i] == ')') {
                // 在当前为')'的情况下,如果前一个为'(',用前前一个的最长包含有效括号的子串长度加2即可
                if(s[i-1] == '(') 
                    dp[i] = (i >= 2 ? dp[i-2] : 0) + 2;
                // 如果前一个为')',例如:"()(()())",并且s[i - dp[i-1] - 1]也为'('时,dp[i]才不为0,此时还需要考虑dp[i - dp[i-1] - 2]的值
                else if(i - dp[i-1] - 1 >= 0 && s[i - dp[i-1] - 1] == '(') 
                    dp[i] = (i - dp[i-1] - 2 >= 0 ? dp[i - dp[i-1] - 2] : 0) + dp[i-1] + 2;
                maxx = max(maxx, dp[i]); // 更新最长包含有效括号的子串长度
            }
        }
        return maxx;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值