1249. Minimum Remove to Make Valid Parentheses**

1249. Minimum Remove to Make Valid Parentheses**

https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/

题目描述

Given a string s of '(' , ')' and lowercase English characters.

Your task is to remove the minimum number of parentheses ( '(' or ')', in any positions ) so that the resulting parentheses string is valid and return any valid string.

Formally, a parentheses string is valid if and only if:

  • It is the empty string, contains only lowercase characters, or
  • It can be written as AB (A concatenated with B), where A and B are valid strings, or
  • It can be written as (A), where A is a valid string.

Example 1:

Input: s = "lee(t(c)o)de)"
Output: "lee(t(c)o)de"
Explanation: "lee(t(co)de)" , "lee(t(c)ode)" would also be accepted.

Example 2:

Input: s = "a)b(c)d"
Output: "ab(c)d"

Example 3:

Input: s = "))(("
Output: ""
Explanation: An empty string is also valid.

Example 4:

Input: s = "(a(b(c)d)"
Output: "a(b(c)d)"

Constraints:

  • 1 <= s.length <= 10^5
  • s[i] is one of '(' , ')' and lowercase English letters.

C++ 实现 1

使用两个栈分别存储 ( 以及 ) 的索引. 使用哈希表 record 统计要删除的符号的索引. 使用栈的好处是, 对于 ( 可以找到最近的匹配的 ).

class Solution {
public:
    string minRemoveToMakeValid(string s) {
        stack<int> left, right;
        for (int i = 0; i < s.size(); ++ i) {
            if (s[i] == '(') left.push(i);
            else if (s[i] == ')') right.push(i);
        }
        unordered_set<int> record;
        while (!left.empty() && !right.empty()) {
            auto a = left.top(), b = right.top();
            // 如果存在 ( 出现在 ) 后面的情况, 比如上面的 
            // example3 "))((", 那么删除 (
            // 否则, 说明两者刚好配对, 同时弹出. 
            if (a > b) {
                record.insert(a);
                left.pop();
            } else {
                left.pop();
                right.pop();
            }
        }
        // 如果存在 ( 和 ) 不完全匹配的情况,
        // 将索引加入 record
        while (!left.empty()) {
            record.insert(left.top());
            left.pop();
        }
        while (!right.empty()) {
            record.insert(right.top());
            right.pop();
        }
        string res;
        // 删除出现在 record 中的字符
        for (int i = 0; i < s.size(); ++ i) {
            if (!record.count(i)) res += s[i];
        }
        return res;
    }
};

C++ 实现 2

来自 Java/C++ Stack. 该解法使用一个栈, 保存 ( 的索引.

  • 如果找到匹配的 ), 那么将 ( 弹出
  • 如果 ) 多余, 将其替换为 *, 用 * 表示该符号最后要删除
  • 如果最后发现 ( 多余, 将这些 ( 替换为 *

最后灵活应用库函数 std::remove 删除 * (移到 s 的末尾).

class Solution {
public:
    string minRemoveToMakeValid(string s) {
      stack<int> st;
      for (auto i = 0; i < s.size(); ++i) {
          if (s[i] == '(') st.push(i);
          if (s[i] == ')') {
              if (!st.empty()) st.pop();
              else s[i] = '*';
          }
      }
      while (!st.empty()) {
          s[st.top()] = '*';
          st.pop();
      }
      s.erase(remove(s.begin(), s.end(), '*'), s.end());
      return s;
    }
};

C++ 实现 3

来自 LeetCode 的 Submission. 和 C++ 实现 2 思路一致, 只不过要删除的符号用 ' ' 来替代. 另一方面, 不采用 stack 保存 (, 而是用 sum 统计 ( 的个数.

class Solution {
public:
    string minRemoveToMakeValid(string &s) {
        const int n = s.size();
        int sum = 0;
        for (int i = 0; i < n; ++i) {
            if (s[i] == '(') ++sum;
            else if (s[i] == ')') {
                if (sum) --sum;
                else s[i] = ' ';
            }
        }
        for (int i = n - 1; i >= 0 && sum; --i)
            if (s[i] == '(') --sum, s[i] = ' ';
        string ans;
        for (char c : s) if (c != ' ') ans += c;
        return ans;
    }
};

你可能感兴趣的:(LeetCode,leetcode,算法)