[LeetCode] 301. Remove Invalid Parentheses 移除非法括号

Posted 轻风舞动

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode] 301. 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.

Subscribe to see which companies asked this question

思路:

题意是给出一个string,其中的小括号可能不配对,移除不配对的括号,返回所有的解。

首先,如何判断括号是否合法。可以用栈,这也是栈这个数据结构的一个典型应用。也可用一个count计数器,遇到左括号++,右括号--,一旦count小于0,就说明不合法。比较推荐count方式,空间复杂度较低。

BFS: 枚举去除的点,当找到后停止BFS树的扩展(因为要去除最少括号,所以即使有其他的结果,也一定在同一层)

DFS: 统计左右括号能删的个数,进行DFS。

Java: DFS

Calculate the number of invalid parentheses of the original string. Iterate through the string. Remove each character and DFS if the number of invalid parentheses decreases.
This solution is based on the fact that if we‘re on the right path to the optimal string, the number of invalid parentheses must always decrease.

Time complexity:
In the worst case, I could have some input like "))))))))", where I need to search through the entire string. The good thing is duplicates will be pruned by the hash set. Calculating mis-match takes O(n). So the overall time complexity is O(n^2).

class Solution {
    public List<String> removeInvalidParentheses(String s) {
        List<String> list = new ArrayList<>();
        Set<String> visited = new HashSet<>();
        removeInvalidParentheses(s, numberOfInvalid(s), list, visited);
        return list;
    }
    
    private void removeInvalidParentheses(String s, int invalid, List<String> list, Set<String> visited) {
        if (invalid == 0) {
            list.add(s);
            return;
        }
        
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) != ‘(‘ && s.charAt(i) != ‘)‘) {
                continue;
            }
            
            String child = s.substring(0, i) + s.substring(i + 1, s.length());
            if (!visited.contains(child)) {
                visited.add(child);
                int next = numberOfInvalid(child);
                
                if (next < invalid) {
                    removeInvalidParentheses(child, next, list, visited);
                }
            }
        }
    }
    
    private int numberOfInvalid(String s) {
        int open = 0;
        int close = 0;
        
        for (char c : s.toCharArray()) {
            if (c == ‘(‘) {
                open++;
            } else if (c == ‘)‘) {
                if (open == 0) {
                    close++;
                } else {
                    open--;
                }
            }
        }
        return open + close;
    }
}

Java: BFS

Thought process:
BFS:
Graph definition:
Vertex: a candidate string.
Edge: two strings s1 and s2 have an edge if s1 equals s2 with one parenthesis deleted.
Put string into a queue.
For the current size of the queue, poll a string from the queue.
Iterate through the string. For each character, remove it, and check if the parentheses are valid.
If so, iterate over current level and return the result.
If not, offer the new string to the queue.

Time complexity:
Say the string‘s length is n. For every character, the choice is to keep or remove. So there are 2^n total states to check. Check if a string is valid is O(1). So the overall time complexity is O(2^n).

class Solution {
    public List<String> removeInvalidParentheses(String s) {
        List<String> list = new ArrayList<>();
        Queue<String> queue = new LinkedList<>();
        queue.offer(s);
        Set<String> visited = new HashSet<>();
        visited.add(s);
        
        boolean found = false;
        while (!found && !queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                String str = queue.poll();
                if (isValid(str)) {
                    list.add(str);
                    found = true;
                    continue;
                }
                
                for (int j = 0; j < str.length(); j++) {
                    if (str.charAt(j) != ‘(‘ && str.charAt(j) != ‘)‘) {
                        continue;
                    }
                    
                    String child = str.substring(0, j) + str.substring(j + 1);
                    if (!visited.contains(child)) {
                        queue.offer(child);
                        visited.add(child);
                    }
                }
            }
        }
        return list;
    }
    
    private boolean isValid(String s) {
        int open = 0;
        for (char c : s.toCharArray()) {
            if (c == ‘(‘) {
                open++;
            } else if (c == ‘)‘) {
                if (open == 0) {
                    return false;
                }
                open--;
            }
        }
        return open == 0;
    }
}

Python: DFS

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        def dfs(s):
            mi = calc(s)
            if mi == 0:
                return [s]
            ans = []
            for x in range(len(s)):
                if s[x] in (‘(‘, ‘)‘):
                    ns = s[:x] + s[x+1:]
                    if ns not in visited and calc(ns) < mi:
                        visited.add(ns)
                        ans.extend(dfs(ns))
            return ans    
        def calc(s):
            a = b = 0
            for c in s:
                a += {‘(‘ : 1, ‘)‘ : -1}.get(c, 0)
                b += a < 0
                a = max(a, 0)
            return a + b

        visited = set([s])    
        return dfs(s)

Python: BFS

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        def calc(s):
            a = b = 0
            for c in s:
                a += {‘(‘ : 1, ‘)‘ : -1}.get(c, 0)
                b += a < 0
                a = max(a, 0)
            return a + b

        visited = set([s])
        ans = []
        queue = collections.deque([s])
        done = False
        while queue:
            t = queue.popleft()
            mi = calc(t)
            if mi == 0:
                done = True
                ans.append(t)
            if done:
                continue
            for x in range(len(t)):
                if t[x] not in (‘(‘, ‘)‘):
                    continue
                ns = t[:x] + t[x+1:]
                if ns not in visited and calc(ns) < mi:
                    visited.add(ns)
                    queue.append(ns)

        return ans

Python: DFS

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        if not s: return [‘‘]
        left_remove = right_remove = 0
        for c in s:
            if c == ‘(‘:
                left_remove += 1
            elif c == ‘)‘:
                if left_remove:
                    left_remove -= 1
                else:
                    right_remove += 1
 
        ans = set()
        self.dfs(0, left_remove, right_remove, 0, ‘‘, s, ans)
        return list(ans)
 
    def dfs(self, index, left_remove, right_remove, left_pare, cur, s, ans):
        if left_remove < 0 or right_remove < 0 or left_pare < 0: return
        if index == len(s):
            if left_remove == right_remove == left_pare == 0:
                ans.add(cur)
            return
 
        if s[index] == ‘(‘:
            self.dfs(index + 1, left_remove - 1, right_remove, left_pare, cur, s, ans)
            self.dfs(index + 1, left_remove, right_remove, left_pare + 1, cur + s[index], s, ans)
        elif s[index] == ‘)‘:
            self.dfs(index + 1, left_remove, right_remove - 1, left_pare, cur, s, ans)
            self.dfs(index + 1, left_remove, right_remove, left_pare - 1, cur + s[index], s, ans)
        else:
            self.dfs(index + 1, left_remove, right_remove, left_pare, cur + s[index], s, ans)

Python: BFS

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        if not s: return [‘‘]
        q, ans, vis = [s], [], set([s])
        found = False
        while q:
            cur = q.pop(0)
            if self.isValidParentheses(cur):
                found = True
                ans.append(cur)
            elif not found:
                for i in xrange(len(cur)):
                    if cur[i] == ‘(‘ or cur[i] == ‘)‘:
                        t = cur[:i] + cur[i + 1:]
                        if t not in vis:
                            q.append(t)
                            vis.add(t)
        return ans
 
    def isValidParentheses(self, s):
        cnt = 0
        for c in s:
            if c == ‘(‘:
                cnt += 1
            elif c == ‘)‘:
                if cnt == 0: return False
                cnt -= 1
        return cnt == 0

Python: BFS, concise

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        if not s: return [‘‘]
        q = {s}
        while q:
            ans = filter(self.isValidParentheses,q)
            if ans: return ans
            q = {cur[:i] + cur[i + 1:] for cur in q for i in xrange(len(cur))}
 
    def isValidParentheses(self, s):
        cnt = 0
        for c in s:
            if c == ‘(‘:
                cnt += 1
            elif c == ‘)‘:
                if cnt == 0: return False
                cnt -= 1
        return cnt == 0

C++:

class Solution {
public:
    vector<string> removeInvalidParentheses(string s) {
        vector<string> res;
        unordered_set<string> visited{{s}};
        queue<string> q{{s}};
        bool found = false;
        while (!q.empty()) {
            string t = q.front(); q.pop();
            if (isValid(t)) {
                res.push_back(t);
                found = true;
            }
            if (found) continue;
            for (int i = 0; i < t.size(); ++i) {
                if (t[i] != ‘(‘ && t[i] != ‘)‘) continue;
                string str = t.substr(0, i) + t.substr(i + 1);
                if (!visited.count(str)) {
                    q.push(str);
                    visited.insert(str);
                }
            }
        }
        return res;
    }
    bool isValid(string t) {
        int cnt = 0;
        for (int i = 0; i < t.size(); ++i) {
            if (t[i] == ‘(‘) ++cnt;
            else if (t[i] == ‘)‘ && --cnt < 0) return false;
        }
        return cnt == 0;
    }
};

  

以上是关于[LeetCode] 301. Remove Invalid Parentheses 移除非法括号的主要内容,如果未能解决你的问题,请参考以下文章

[LeetCode] 301. Remove Invalid Parentheses

leetcode 301-Remove Invalid Parentheses(hard)

[leetcode]301. Remove Invalid Parentheses 去除无效括号

[LeetCode] 301. Remove Invalid Parentheses 移除非法括号

LeetCode 301. Remove Invalid Parentheses(DP)

leetcode301. Remove Invalid Parentheses