301. Remove Invalid Parentheses

问题:

给定一个字符串,包含左右小括号+字母。

对该字符串进行【括号删减】,使得 字符串中括号完全匹配。"( )"

求最少删减字符,能得到的所有完全匹配的字符串。

Example 1:
Input: "()())()"
Output: ["()()()", "(())()"]

Example 2:
Input: "(a)())()"
Output: ["(a)()()", "(a())()"]

Example 3:
Input: ")("
Output: [""]

  

解法:Backtracking(回溯算法)

前期准备:

遍历字符串,遇到"(" count++,遇到")" count--

那么匹配的正常字符串的count变化应该总是符合:count>=0....最终count==0

若期间只要有count<0,那么这时一定多余出来一个")"

计算这样多余出来的")"的个数:minright

去掉这些不符合条件的")",最后,得到count>0,则为多出来的"(",计数为minleft

 

Backtracking:

状态:

  • 到目前位置pos为止,删减括号,得到的正确字符串path。
  • 这时,剩下可删减的"("个数:left
  • 剩下可删减的")"个数:right
  • 当前的count状态,由于path为正确字符串,那么count一定>=0,若<0,则不符合要求,直接返回。

选择:

  • 当前字符:s[pos]
    • "(" 且 还可删减 left>0:对s[pos]删除:path, count, left--, right
    • ")" 且 还可删减 right>0:对s[pos]删除:path, count, left, right--
  • 不删减:若s[pos]:path+s[pos], count(做以下处理), left, right
    • "(" :count++
    • ")" :count--

递归退出条件:

  • pos==s.length
    • 若left==right==count==0 则 res.push_back(path),再return
    • 否则直接return
  • 若count<0, 直接return。当前path已经不满足括号匹配要求。

 

代码参考:

 1 class Solution {
 2 public:
 3    // int cc = 0;
 4    // void print_intend() {
 5    //     for(int i=0; i<cc; i++) {
 6    //         printf("  ");
 7    //     }
 8    // }
 9     void backtrack(unordered_set<string>& res, string path, int pos, int count, int left, int right, string& s) {
10         if(count<0) return;
11         if(pos==s.length()) {
12             if(left==0 && right==0 && count==0) {
13                 res.insert(path);
14     //            print_intend();
15     //            printf("return res.last:%s.\n", path.c_str());
16             }
17             return;
18         }
19         if(s[pos]=='(' && left>0) {
20     //        print_intend();
21     //        printf("count:%d, left:%d, right:%d. path:%s\n", count, left-1, right, path.c_str());
22      //       cc++;
23             backtrack(res, path, pos+1, count, left-1, right, s);
24      //       cc--;
25         } else if(s[pos]==')' && right>0) {
26     //        print_intend();
27     //        printf("count:%d, left:%d, right:%d. path:%s\n", count, left, right-1, path.c_str());
28      //       cc++;
29             backtrack(res, path, pos+1, count, left, right-1, s);
30      //       cc--;
31         }
32         switch(s[pos]) {
33             case '(': count++; break;
34             case ')': count--; break;
35             default: break;
36         }
37     //        print_intend();
38     //        printf("--count:%d, left:%d, right:%d. path:%s\n", count, left, right, path.c_str());
39     //    cc++;
40         backtrack(res, path+s[pos], pos+1, count, left, right, s);
41     //    cc--;
42         return;
43     }
44     vector<string> removeInvalidParentheses(string s) {
45         unordered_set<string> res;
46         string path;
47         int minleft = 0, minright = 0, count = 0;
48         for(char c:s) {
49             switch(c) {
50                 case '(': count++; break;
51                 case ')': count--; break;
52                 default: break;
53             }
54             if(count<0) {
55                 minright++;//')'
56                 count++;
57             }
58         }
59         minleft=count;//'('
60         backtrack(res, path, 0, 0, minleft, minright, s);
61         return vector<string>(res.begin(), res.end());
62     }
63 };

 

posted @ 2021-02-27 11:20  habibah_chang  阅读(79)  评论(0编辑  收藏  举报