leetcode 301. 删除无效的括号

2 篇文章 0 订阅
1 篇文章 0 订阅

建立决策树的BFS、DFS题。

有两种解法。
我的两种解法优化的都不是很好,不论是时间还是空间都没有进50%

BFS解法
要用set来解决掉重复元素。
用unordered_set要比set快很多

https://leetcode-cn.com/problems/remove-invalid-parentheses/

class Solution {
public:
    vector<string> res;

    void BFS(string s) {
        queue<string> qu;
        queue<int> temp;
        unordered_set<string> st;
        qu.push(s);
        temp.push(0);
        st.insert(s);

        int num;
        int nowLevel;
        int minLevel = 999;
        while (!qu.empty()) {
            s = qu.front();     qu.pop();
            nowLevel = temp.front();    temp.pop();
            num = 0;
            for (int i = 0; i < s.size(); i ++) {
                if (s[i] == '(')    num ++;
                else if (s[i] == ')')   num --;
                if (num < 0)    break;
            }

            if (nowLevel > minLevel)    return ;

            if (num == 0 && count(res.begin(), res.end(), s) == 0) {
                res.push_back(s);
                minLevel = nowLevel;
            } 

            string ts = s;
            string::iterator it;
            for (it = s.begin(); it != s.end(); it ++) {
                if (!(*it == '(' || *it == ')'))    continue;
                s.erase(it);
                if (!st.count(s)) {
                    qu.push(s);
                    st.insert(s);
                    temp.push(nowLevel + 1);
                }
                s = ts;
            }
        }
    }

    vector<string> removeInvalidParentheses(string s) {
        BFS(s);
        return res;
    }
};

DFS解法:疯狂剪枝

剪枝1:提前计算好需要删除的左右括号个数m,当到达删除个数时就判断。相当于只留下决策树的前m层
剪枝2:可能会出现相同的字符串,将相同的剪掉。比如DFS的过程中出现了“(())”,那么该字符串就不能再次出现。

总结:
可以通过两个方面剪枝,
1.层数
2.删去重复个数

class Solution {
public:
    vector<string> res;
    unordered_set<string> st;
    bool check(string s) {
        int num = 0;
        for (char i : s) {
            if (i == '(')    num ++;
            else if (i == ')')   num --;
            if (num < 0)    return false;
        }
        if (num == 0)   return true;
        else return false;
    }

    void DFS(string s, int left, int right) {
        st.insert(s);
        if (left == 0 && right == 0) {
            if (check(s)) {
                res.push_back(s);
            }
            return ;
        }

        string::iterator it;
        string ts = s;
        for (it = s.begin(); it != s.end(); it ++) {
            if (*it == '(' && left > 0) {
                s.erase(it);
                if (!st.count(s)) DFS(s, left - 1, right);
                s = ts;
            } else if (*it == ')' && right > 0) {
                s.erase(it);
                if (!st.count(s)) DFS(s, left, right - 1);
                s = ts;
            }
        }

    }

    vector<string> removeInvalidParentheses(string s) {
        int left = 0, right = 0;

        for (int i = 0; i < s.size(); i ++) {
            if (s[i] == '(') {
                left ++;
            } else if (s[i] == ')') {
                if (left > 0)   left --;
                else right ++;
            }
        }
        DFS(s, left, right);
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值