遍历每个算符,每个算符把表达式分成左右两个子问题。

逻辑表达式加括号的方式数

给定只有0、1、&、|、^ 的布尔表达式,和期望的结果result,求加括号的方式数。如 countEval("1^0|0|1", false) -> 2,countEval("0&0&0&1^1|1", true) -> 10

int countEval(String s, boolean result) {
    if (s.length() == 0) return 0;
    if (s.length() == 1) return s.equals("1") == result ? 1 : 0;

    int ways = 0;
    for (int i = 1; i < s.length(); i += 2) { // 遍历每个算符
        char c = s.charAt(i);
        String left = s.substring(0, i);
        String right = s.substring(i + 1, s.length());

        int leftTrue = countEval(left, true);
        int leftFalse = countEval(left, false);
        int rightTrue = countEval(right, true);
        int rightFalse = countEval(right, false);
        int total = (leftTrue + leftFalse) * (rightTrue + rightFalse);

        int totalTrue = 0;
        if (c == '&') {
            totalTrue = leftTrue * rightTrue;
        } else if (c == '|') {
            totalTrue = leftTrue * rightTrue + leftFalse * rightTrue + leftTrue * rightFalse;
        } else if (c == '^') {
            totalTrue = leftTrue * rightFalse + leftFalse * rightTrue;
        }

        ways += result ? totalTrue : total - totalTrue;
    }
    return ways;
}

会重复计算子问题,要用备忘录memo缓存计算结果(s+result => count)。

加减乘表达式加括号计算的所有结果

vector<int> diffWaysToCompute(string input) {
    vector<int> ans;
    for (int i = 0; i < input.size(); i++) {
        char c = input[i];
        if (c == '+' || c == '-' || c == '*') { // 分治
            auto ans1 = diffWaysToCompute(input.substr(0, i));
            auto ans2 = diffWaysToCompute(input.substr(i + 1));
            for (auto n1 : ans1) {
                for (auto n2 : ans2) {
                    if (c == '+') {
                        ans.push_back(n1 + n2);
                    } else if (c == '-') {
                        ans.push_back(n1 - n2);
                    } else {
                        ans.push_back(n1 * n2);
                    }
                }
            }
        }
    }
    if (ans.empty()) { // input是纯数字串
        ans.push_back(stoi(input));
    }
    return ans;
}