程序員面試金典 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;
        }
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章