zoukankan      html  css  js  c++  java
  • 括号问题系列

    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;
            }
    };
    

      

     

  • 相关阅读:
    LIKE语句也可以这样写
    a链接触发javascript函数导致innerHTML里的图片无法加载
    引用类型真屌
    网站建设心得
    SPAN
    Go! 环境配置和入门
    linux内核编译
    面试题
    KCMT开源控件之方便简洁的分页控件
    c#中out、ref和params的用法与区别
  • 原文地址:https://www.cnblogs.com/E-Dreamer-Blogs/p/13233847.html
Copyright © 2011-2022 走看看