程序员面试金典 8.14

Boolean Evaluation:给定一个只含有10&|^的布尔表达式,求所有加括号的方式,使得该表达式的值为result,不考虑多余括号的情况。

与其说加括号,不如说决定每个位运算符的被求值的顺序,首先选定一个运算符作为最后求值的运算符,该运算符将表达式分成了两部分,在左右两部分都被求值后,根据该运算符的运算规则,求出整个表达式的值。

基本思路有了,还需要稍微变化一下。因为整个表达式的值已经确定为result了,所以要根据左右表达式取值真假的个数和运算符的含义,使用乘法公式计算。

class Solution {
public:
    int countEval(string s, int result) {
        expr.assign(s);
        Count.assign(expr.size(), vector<pair<int, int>>(expr.size() + 1, pair<int, int>(-1, -1)));
        return countEval(0, expr.size(), result == 1 ? true : false);
    }
private:
    string expr;
    vector<vector<pair<int, int>>> Count;
    int countEval(size_t begin, size_t end, bool bRes)
    {
        if(begin + 1 == end){
            if(expr[begin] == '1' && bRes) return 1;
            else if(expr[begin] == '0' && !bRes) return 1;
            else return 0;
        }
        if(bRes && Count[begin][end].first != -1) return Count[begin][end].first;
        if(!bRes && Count[begin][end].second != -1) return Count[begin][end].second;
        int lt, lf, rt, rf, t;
        pair<int, int> sum(0, 0);
        for(size_t op = begin + 1; op < end; op += 2)
        {
            lt = countEval(begin, op, true);
            lf = countEval(begin, op, false);
            rt = countEval(op + 1, end, true);
            rf = countEval(op + 1, end, false);
            t = evalTrue(expr[op], lt, lf, rt, rf);
            sum.first += t;
            sum.second += (lt + lf) * (rt + rf) - t;
        }
        Count[begin][end] = sum;
        if(bRes) return sum.first;
        else return sum.second;
    }
    int evalTrue(char c, int lt, int lf, int rt, int rf)
    {
        switch(c)
        {
            case '&':
                return lt * rt;
            case '|':
                return lt * (rt + rf) + lf * rt;
            case '^':
                return lt * rf + lf * rt;
            default:
                return 0;
        }
    }
};
发布了194 篇原创文章 · 获赞 2 · 访问量 7708

猜你喜欢

转载自blog.csdn.net/RayoNicks/article/details/105500278
今日推荐