leetcode20、22——有效括号问题(判断有效的括号以及生成有效的括号)

1、判断有效的括号

1.1、题目

题目链接
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

输入: "()"
输出: true

输入: "()[]{}"
输出: true

输入: "(]"
输出: false

输入: "([)]"
输出: false

1.2、思路

核心思路:,首先我们应该明确如下两条规则:

  • 1、一个「合法」括号组合的左括号数量一定等于右括号数量
  • 2、对于一个「合法」的括号字符串组合 p,必然对于任何 0 <= i < len ( p) 都有:子串 p[0..i]左括号的数量大于或等于右括号的数量
    • 因为从左往右算的话,肯定是左括号多嘛,到最后左右括号数量相等

我们先处理一种括号:

  • 每个右括号 ) 的左边必须有一个左括号 ( 和它匹配
bool isValid(string str) {
    // 待匹配的左括号数量
    int left = 0;
    for (char c : str) {
        if (c == '(')
            left++;
        else // 遇到右括号
            left--;

        if (left < 0)
            return false;
    }
    return left == 0;
}

对于三种括号的情况,用一个名为 left 的代替之前思路中的 left 变量,遇到左括号就入栈遇到右括号就去栈中寻找最近的左括号,看是否匹配。

1.3、题解

class Solution {
public:
    bool isValid(string s) {
        int len = s.size();
        if(len % 2 != 0)
            return false;
        stack<char>stack;
        map<char,char>m = {{')','('},{']','['},{'}','{'}};//注意这里面括号的顺序,根据右侧括号,找左侧
        for(int i = 0;i < len ;i++)
        {
            if(s[i] == '(' || s[i] == '[' || s[i] == '{')
                stack.push(s[i]);//遇到左括号就push
            else
            {
                if(stack.empty())
                    return false;
                if(m[s[i]] == stack.top())
                    stack.pop();//遇到右括号就pop
                else
                    return false;
            }
        }
        return stack.empty();
    }
};

2、生成有效的括号

2.1、题目

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

输入:n = 3
输出:[
       "((()))",
       "(()())",
       "(())()",
       "()(())",
       "()()()"
     ]

2.2、思路

对于括号合法性的判断,主要是借助「栈」这种数据结构,而对于括号的生成,一般都要利用回溯递归的思想。

重复两条规则:

  • 1、一个「合法」括号组合的左括号数量一定等于右括号数量
  • 2、对于一个「合法」的括号字符串组合 p,必然对于任何 0 <= i < len ( p) 都有:子串 p[0..i]左括号的数量大于或等于右括号的数量
    • 因为从左往右算的话,肯定是左括号多嘛,到最后左右括号数量相等

对于 2n 个位置,必然有 n 个左括号n 个右括号,用 left 记录还可以使用多少个左括号,用 right 记录还可以使用多少个右括号

2.3、题解

vector<string> generateParenthesis(int n) {
    if (n == 0) return {};
    // 记录所有合法的括号组合
    vector<string> res;
    // 回溯过程中的路径
    string track;
    // 可用的左括号和右括号数量初始化为 n
    backtrack(n, n, track, res);
    return res;
}

// 可用的左括号数量为 left 个,可用的右括号数量为 rgiht 个
void backtrack(int left, int right, 
            string& track, vector<string>& res) {
    // 若左括号剩下的多,说明不合法。剩的多因为用的少嘛,左侧先填充的,所以就这样了。
    if (right < left) return;
    // 数量小于 0 肯定是不合法的
    if (left < 0 || right < 0) return;
    // 当所有括号都恰好用完时,得到一个合法的括号组合
    if (left == 0 && right == 0) {
        res.push_back(track);
        return;
    }

    // 尝试放一个左括号
    track.push_back('('); // 选择
    backtrack(left - 1, right, track, res);
    track.pop_back(); // 撤消选择

    // 尝试放一个右括号
    track.push_back(')'); // 选择
    backtrack(left, right - 1, track, res);
    track.pop_back();// 撤消选择
}

参考

https://labuladong.gitbook.io/algo/suan-fa-si-wei-xi-lie/he-fa-kuo-hao-sheng-cheng

猜你喜欢

转载自blog.csdn.net/JMW1407/article/details/107732621