zoukankan      html  css  js  c++  java
  • LeetCode-Remove Invalid Parentheses

    Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.

    Note: The input string may contain letters other than the parentheses ( and ).

    Examples:

    "()())()" -> ["()()()", "(())()"]
    "(a)())()" -> ["(a)()()", "(a())()"]
    ")(" -> [""]
    

    Credits:
    Special thanks to @hpplayer for adding this problem and creating all test cases.

    Analysis:

    Example: '())())()))'

    We need to remove AT LEAST 1 ')' before s[2] (included), AT LEAST 2 ')' before s[5], AT LEAST 3 ')' before s[8] and finally in a total of 4 ')' for the whole string. It is easy to get this information, this implies two things:

    1. If we count ')' for -1 and '(' for 1, then whenever we get count==-1, we need delete 1 ')' to make the current prefix valid. The ways of deletion include one ')' in every SECTION of ')', for example,

    for '())())', we can delete one ')' from the first '))' or the second '))'. Once we make the prefix valid, we can move forward.

    2. HOWEVER, only considerring 1. is not sufficient! Notice the word 'AT LEAST'. This means that we can actuall delete more than 1 ')' in some prefix given that there are more ')' in the suffix. Example,

    for this '())())' and its prefix '())', we should delete at least 1 ')' but we can also delete 2 ')', because in the following, we have one more ')', i.e., we need to delete in a total of 2 ')'.

    So, when we delete one ')' for '())' and move forward, we should record the one we deleted (saying lastRemoved), and if we need delete more in the following, we should start our consideration from lastRemoved+1.

    Solution:

    public class Solution {
        public List<String> removeInvalidParentheses(String s) {
            List<String> resList = new ArrayList<String>();
            removeParentheseRecur(s, resList, true, 0, 0, ')', '(');
            return resList;
        }
    
        public void removeParentheseRecur(String s, List<String> resList, boolean leftToRight, int nextIndex,
                int removeStart, char target, char other) {
            int count = 0;
            for (int i = nextIndex; i < s.length(); i++) {
                if (s.charAt(i) == other) {
                    count++;
                }
                if (s.charAt(i) == target) {
                    count--;
                }
                if (count < 0) {
                    // Remove one target char from [removeStart...i].
                    for (int j = removeStart; j <= i; j++)
                        // Remove current target char, either it is the first target
                        // in the range or it is in another section, e.g., ')())',
                        // we will consider the [0] and [2], but not [3].
                        if (s.charAt(j) == target && (j == removeStart || s.charAt(j - 1) != target)) {
                            // Since we removed one char from [0...i], the nextIndex
                            // (should be i+1) is i and the removeStart (should be
                            // j+1) is j now.
                            removeParentheseRecur(s.substring(0, j) + s.substring(j + 1, s.length()), resList, leftToRight,
                                    i, j, target, other);
                        }
                    return;
                }
            }
            // We always need to reverse the string, because if it is left to right, we need reverse from right to left;
            // if it is right to left, we need reverse the answer back to left to right order.
            String reverse = new StringBuilder(s).reverse().toString();
            if (leftToRight) {
                // After deleting all invalid ')' from left to right, we delete
                // invalid '(' from right to left.
                removeParentheseRecur(reverse, resList, false, 0, 0, '(', ')');
            } else {
                resList.add(reverse);
            }
    
        }
    }
  • 相关阅读:
    直接初始化和复制初始化
    C++ 内连接与外连接 (转)
    mysql-Innodb事务隔离级别-repeatable read详解(转)
    Linux操作系统多线程信号总结
    Keil MDK 5.14 仿真时System Viewer菜单显示空白和Peripherals菜单无外设寄存器
    转载傅里叶级数和傅里叶变换的理解 https://www.cnblogs.com/h2zZhou/p/8405717.html
    SPI总线的原理与Verilog实现
    SD 模拟sip 读写子程序
    SD卡 模拟SPI总线控制流程
    SD卡spi读写流程
  • 原文地址:https://www.cnblogs.com/lishiblog/p/5836150.html
Copyright © 2011-2022 走看看