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())()"]
    ")(" -> [""]

    DFS solution with optimizations:

    1. Before starting DFS, calculate the total numbers of opening and closing parentheses that need to be removed in the final solution, then these two numbers could be used to speed up the DFS process.
    2. Use while loop to avoid duplicate result in DFS, instead of using HashSet.
    3. Use count variable to validate the parentheses dynamically.

    openN and closeN means the total numbers of opening and closing parentheses that need to be removed in the final solution (removed the minimum number of invalid parentheses).

    diff means in the stringbuffer we build, #of '(' minus # of ')'. If at some recursion, diff<0. that's not valid expression, should directly return.

    This diff here is not just for pruning, but also have the important meaning to make sure that stringbuffer is always correct. So we must have a diff in the recursion

    sb.append(arr, cur, i);

    dfs(s, cur + i, diff + i, openN, closeN, res, sb) means not to remove the current parenthesis, keep it in stringbuffer sb.

    dfs(s, cur + 1, diff, openN - 1, closeN, result, sb) means to remove the current parenthesis. We won't need to do the dfs if openN has been decreased to zero - if the openN is zero, that means there are already enough open parentheses has been removed, and continually removing open parenthesis won't be a possible solution.

    Watch out for duplicate. If red means keep in stringbuffer and white means remove, then the following case are duplicate: 

    1. ( ( )

    2. ( ( )

    3. ( ( )

    So our strategy is as 45 and 58 line shows: if you choose to keep one parenthese, then you have to keep all the following same parentheses

    for the above cases, we only have 

    1. ( ( )

    2. ( )

     1 public class Solution {
     2     public List<String> removeInvalidParentheses(String s) {
     3         List<String> res = new ArrayList<String>();
     4         if (s==null || s.length()==0)  {
     5             res.add("");
     6             return res;
     7         }
     8         int diff=0, openN=0, closeN=0; 
     9         char[] arr = s.toCharArray();
    10         for (int i=0; i<arr.length; i++) {
    11             if (arr[i] == '(') diff++;
    12             else if (arr[i] == ')') {
    13                 if (diff == 0) closeN++;
    14                 else diff--;
    15             }
    16         }
    17         openN = diff;
    18         diff = 0;
    19         if (openN==0 && closeN==0) {
    20             res.add(s);
    21             return res;
    22         }
    23         
    24         //backtracking
    25         dfs(arr, res, 0, diff, openN, closeN, new StringBuffer());
    26         return res;
    27     }
    28     
    29     public void dfs(char[] arr, List<String> res, int cur, int diff, int openN, int closeN, StringBuffer sb) {
    30         if (diff < 0) return;
    31         if (cur == arr.length) {
    32             if (openN==0 && closeN==0) {
    33                 res.add(sb.toString());
    34             }
    35             return;
    36         }
    37         if (arr[cur]!='(' && arr[cur]!=')') {
    38             sb.append(arr[cur]);
    39             dfs(arr, res, cur+1, diff, openN, closeN, sb);
    40             sb.deleteCharAt(sb.length()-1);
    41         }
    42         else if (arr[cur] == '(') {
    43             //choice one: keep this '(' in stringbuffer, but in order to avoid duplicate, has to keep all consecutive '('
    44             int i=0;
    45             while (cur+i<arr.length && arr[cur+i]=='(') {
    46                 i++;
    47                 sb.append('(');
    48             }
    49             dfs(arr, res, cur+i, diff+i, openN, closeN, sb);
    50             sb.delete(sb.length()-i, sb.length());
    51             
    52             //choice two: remove this '(' in stringbuffer
    53             if (openN > 0) {
    54                 dfs(arr, res, cur+1, diff, openN-1, closeN, sb);
    55             }
    56         }
    57         else if (arr[cur] == ')') {
    58             //choice one: keep this ')' in stringbuffer, but in order to avoid duplicate, has to keep all consecutive ')'
    59             int i=0;
    60             while (cur+i<arr.length && arr[cur+i]==')') {
    61                 i++;
    62                 sb.append(')');
    63             }
    64             dfs(arr, res, cur+i, diff-i, openN, closeN, sb);
    65             sb.delete(sb.length()-i, sb.length());
    66             
    67             //choice two: remove this ')' in stringbuffer
    68             if (closeN > 0) {
    69                 dfs(arr, res, cur+1, diff, openN, closeN-1, sb);
    70             }
    71         }
    72     }
    73     
    74 }
  • 相关阅读:
    Overloaded的方法是否可以改变返回值的类型
    parseXXX的用法
    java的类型转换问题。int a = 123456;short b = (short)a;System.out.println(b);为什么结果是-7616?
    UVA 10405 Longest Common Subsequence(简单DP)
    POJ 1001 Exponentiation(大数处理)
    POJ 2318 TOYS(计算几何)(二分)
    POJ 1265 Area (计算几何)(Pick定理)
    POJ 3371 Flesch Reading Ease (模拟题)
    POJ 3687 Labeling Balls(拓扑序列)
    POJ 1094 Sorting It All Out(拓扑序列)
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/5090524.html
Copyright © 2011-2022 走看看