# 1249

difficulty: Medium

Given a string s of `'('` , `')'` and lowercase English characters.&#x20;

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.

&#x20;

**Example 1:**

<pre><code><strong>Input: s = "lee(t(c)o)de)"
</strong><strong>Output: "lee(t(c)o)de"
</strong><strong>Explanation: "lee(t(co)de)" , "lee(t(c)ode)" would also be accepted.
</strong></code></pre>

**Example 2:**

<pre><code><strong>Input: s = "a)b(c)d"
</strong><strong>Output: "ab(c)d"
</strong></code></pre>

**Example 3:**

<pre><code><strong>Input: s = "))(("
</strong><strong>Output: ""
</strong><strong>Explanation: An empty string is also valid.
</strong></code></pre>

**Example 4:**

<pre><code><strong>Input: s = "(a(b(c)d)"
</strong><strong>Output: "a(b(c)d)"
</strong></code></pre>

&#x20;

**Constraints:**

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

这个题要注意和301的区别。 301 要求的是所有的 minRemove 的结果 这个只需要找到其中的一个结果就好了。 区别在于，找到其中的一个结果，可以用好几种不同的算法。

## Method One

```java
class Solution {
    public String minRemoveToMakeValid(String s) {
        int netCount = 0;
        LinkedList<Integer> indices = new LinkedList<>();

for(int i = 0; i < s.length(); i++) {
           char c = s.charAt(i);
           if( c == '(' ) {
               indices.push(i);
               netCount += 1;
          }
           if( c == ')' ) {
               if( netCount > 0) {
                   netCount -= 1;
                   indices.pop();
              }else {
                   indices.push(i);
              }
          }
      }
       StringBuilder ans = new StringBuilder();
       Set<Integer> indicesSet = new HashSet<Integer>();
       int sizeOfIndices = indices.size();

for( int i = 0; i < sizeOfIndices; i++ ) {
           indicesSet.add(indices.pop());
      }
       for( int i = 0; i < s.length(); i++) {
           char c = s.charAt(i);
           if(indicesSet.contains(i)) {

continue;
          }
           ans.append(c);
      }
       return String.valueOf(ans);
  }

//不用以下的办法是因为 substring 是 O(N);
   // public String removeIth(String s, int i) {
   //     return s.substring( 0 , i ) + s.substring( i + 1 );
   // }
}

```

## Method

以下是一个自己想的方法。原理大致相同。 这个题，O(N) 的解法，扫两遍数组是必须的。

```java
class Solution {
    public String minRemoveToMakeValid(String s) {
        int counter = 0;
        StringBuilder sb = new StringBuilder();
        LinkedList<Integer> leftParenthesesIndices = new LinkedList<>();
        int i = 0;
        while( i < s.length() ){
            if(s.charAt(i) == '('){
                counter += 1;
                leftParenthesesIndices.push(sb.length());
            }
            if(s.charAt(i) == ')'){
                counter -= 1;
                if( counter < 0){
                    i++;
                    counter = 0;
                    continue;
                }
            }
            sb.append(s.charAt(i));
            i++;
        }

        while( counter > 0 ){
            sb.deleteCharAt(leftParenthesesIndices.pop());
            counter--;
        }
        return sb.toString();
    }
}
```

## Method Best!

```java

class Solution {

    public String minRemoveToMakeValid(String s) {

        // Parse 1: Remove all invalid ")"
        StringBuilder sb = new StringBuilder();
        int openSeen = 0;
        int balance = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                openSeen++;
                balance++;
            } if (c == ')') {
                if (balance == 0) continue;
                balance--;
            }
            sb.append(c);
        }

        // Parse 2: Remove the rightmost "("
        StringBuilder result = new StringBuilder();
        int openToKeep = openSeen - balance;
        for (int i = 0; i < sb.length(); i++) {
            char c = sb.charAt(i);
            if (c == '(') {
                openToKeep--;
                if (openToKeep < 0) continue;
            }
            result.append(c);
        }

        return result.toString();
    }
}
```
