E-Dreamer

脚踏实地,仰望星空

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

PS: 本文记录几个经常遇到的 括号问题,其中包括: 有效括号判断、括号生成、最长有效括号等。 

有效括号判断

 

 题目分析: 读题过后,很自然想到一个游戏——《消消乐》,只要遇到成对的()就能抵消,然后最终判断最后剩下的是不是不能成对的,即还有元素则判断为无效括号,否则为有效括号。此题这里借助辅助栈来完成。 

class Solution {
public:
        bool isValid(string str) {
               // 使用栈结构
               stack<char> left;
               for (auto c : str) {
                       if (c == '(' || c == '[' || c == '{') {
                              left.push(c);
                       }
                       else { // 字符是‘)’ 或者 ‘]’ 或者 ‘}’
                              if (!left.empty() && leftOf(c) == left.top()) {
                                      left.pop();
                              }
                              else {
                                      // 和最近的左括号不匹配
                                      return false;
                              }
                       }
               }
               // 是否所有的左括号都被匹配了
               return left.empty();
        }
        char leftOf(char c) {
               if (c == ')') return '(';
               if (c == ']') return '[';
               return '{';
        }
};

括号生成

 

 题目分析: 初看题目,有点像字符串的排列,故很容易往 dfs 那个方面去想,但是我觉得dfs的构造还是比较难想到(太菜),这里主要是通过控制 "(" 和 “)”的数量来进行深搜,请直接看代码。 

// dfs
class Solution {
public:
        vector<string> generateParenthesis(int n) {
               vector<string> res;
               if (n == 0) return res;
               dfs("", 0, 0, n, res);
               return res;
        }
        /**
         * @param curStr 当前递归得到的结果
         * @param left   左括号已经用了几个
         * @param right  右括号已经用了几个
         * @param n      左括号、右括号一共得用几个
         * @param res    结果集
         */
        void dfs(string curStr, int left, int right, int n, vector<string>& res) {
               // 递归终止条件
               if (left == n && right == n) {
                       res.push_back(curStr);
               }
               // 剪枝
               if (left < right) {
                       return;
               }
               if (left < n) {
                       dfs(curStr + "(", left + 1, right, n, res);
               }
               if (right < n) {
                       dfs(curStr + ")", left, right + 1, n, res);
               }
        }
};

动态规划方法(https://leetcode-cn.com/problems/generate-parentheses/solution/zui-jian-dan-yi-dong-de-dong-tai-gui-hua-bu-lun-da)

class Solution3 {
public:
        vector<string> generateParenthesis(int n) {
               if (n == 0) return {};   
               if (n == 1) return { "()" };
               vector<vector<string>> dp(n + 1);//定义状态 dp[i]:使用 i 对括号能够生成的组合。
               dp[0] = { "" };            // 0组括号时记为None
               dp[1] = { "()" };    //# 1组括号只有一种情况
               for (int i = 2; i <= n; i++) { // # 开始计算i组括号时的括号组合
                       for (int j = 0; j < i; j++) {
                              for (string p : dp[j])     //开始遍历 p q ,其中p+q=i-1 , j  作为索引
                                      for (string q : dp[i - j - 1]) {
                                             string str = "(" + p + ")" + q; //dp[i] = "("  + dp[可能的括号对数] + ")" + dp[剩下的括号对数]
                                             dp[i].push_back(str);
                                      }
                       }
               }
               return dp[n];
        }
};

最长有效括号

 

 题目分析: 

方法一: 基于有效括号那一题,很容易想到用stack 来解决,这里的编程思想为,使用stack 来记录 “(” 出现的下标,当“)”出现时, 弹出栈顶元素,并在此时更新最长有效括号的长度信息。 

class Solution {
public:
        int longestValidParentheses(string s) {
               int max_length = 0;
               stack<int> sta;
               sta.push(-1);
               for (int i = 0; i < s.size(); i++) {
                       if (s[i] == '(') {
                              sta.push(i);
                       }
                       else {
                              sta.pop();
                              if (sta.empty()) {
                                      sta.push(i);
                              }
                              else {
                                      max_length = max(max_length, i - sta.top());
                              }
                       }
               }
               return max_length;
        }
};

方法二: (动态规划)

 

 

 

class Solution {
public:
        int longestValidParentheses(string s) {
               int max_length = 0;
               vector<int> dp(s.size());
               for (int i = 1; i < s.size(); i++) {
                       if (s[i] == ')') {
                              if (s[i - 1] == '(') {
                                      if (i >= 2) {
                                             dp[i] = dp[i - 2] + 2;
                                      }
                                      else {
                                             dp[i] = 0 + 2;
                                      }
                              }
                              else if (i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(') {
                                      if (i - dp[i - 1] >= 2) {
                                             dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] +  2;
                                      }
                                      else {
                                             dp[i] = dp[i - 1] + 0 + 2;
                                      }
                              }
                              max_length = max(max_length, dp[i]);
                       }
               }
               return max_length;
        }
};

  

 

 

posted on 2020-07-04 09:51  E-Dreamer  阅读(338)  评论(0编辑  收藏  举报