布尔运算

191 阅读2分钟

「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」。

给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。实现一个函数,算出有几种可使该表达式得出 result 值的括号方法。

LeetCode

image.png

一、分析

布尔结果result,不是0就是1。表达式为奇数个(偶数位上为0|1,奇数位上为逻辑运算符(& | ^))

定义函数f(str, result),返回方法数

L...R上,一定有奇数个字符

L位置的字符和R位置上的字符,非0即1,不能是逻辑运算符号!

返回str[L...R]这一段,为true的方法数和为false的方法数

比如:0~4 & 6~10

如果result为true,那么就得要求0~4返回true,6~10返回true,result才为true

如果result为false,那么0~4返回true,6~10必为false,result才为false。或者0~4返回false,6~10返回true或false

二、实现

public static int countEval(String express, int desired) {
    if (express == null || express.equals("")) {
        return 0;
    }
    char[] exp = express.toCharArray();
    int N = exp.length;
    Info[][] dp = new Info[N][N];
    Info allInfo = func(exp, 0, exp.length - 1, dp);
    return desired == 1 ? allInfo.t : allInfo.f;
}

public static class Info {
    public int t;
    public int f;

    public Info(int tr, int fa) {
        t = tr;
        f = fa;
    }
}

// 限制:
// L...R上,一定有奇数个字符
// L位置的字符和R位置的字符,非0即1,不能是逻辑符号!
// 返回str[L...R]这一段,为true的方法数,和false的方法数
public static Info func(char[] str, int L, int R, Info[][] dp) {
    if (dp[L][R] != null) {
        return dp[L][R];
    }
    int t = 0;
    int f = 0;
    if (L == R) { // base case
        t = str[L] == '1' ? 1 : 0;
        f = str[L] == '0' ? 1 : 0;
    } else { // L..R >=3
        // 每一个种逻辑符号,split枚举的东西
        // 都去试试最后结合
        for (int split = L + 1; split < R; split += 2) {
            Info leftInfo = func(str, L, split - 1, dp);
            Info rightInfo = func(str, split + 1, R, dp);
            int a = leftInfo.t;
            int b = leftInfo.f;
            int c = rightInfo.t;
            int d = rightInfo.f;
            switch (str[split]) {
                case '&':
                    t += a * c;
                    f += b * c + b * d + a * d;
                    break;
                case '|':
                    t += a * c + a * d + b * c;
                    f += b * d;
                    break;
                case '^':
                    t += a * d + b * c;
                    f += a * c + b * d;
                    break;
            }
        }

    }
    dp[L][R] = new Info(t, f);
    return dp[L][R];
}

三、总结

int f(str,F/T)

范围尝试模型

不是0就是1的位置为X

逻辑运算符的位置为Y

怎么划分可能性:以奇数位置划分逻辑运算符的情况下