leetcode 面试题 08.14. 布尔运算

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

示例 1:

输入: s = "1^0|0|1", result = 0

输出: 2
解释: 两种可能的括号方法是
1^(0|(0|1))
1^((0|0)|1)
示例 2:

输入: s = "0&0&0&1^1|0", result = 1

输出: 10
提示:

运算符的数量不超过 19

方法:
作者:JustBruteForce
链接:https://leetcode-cn.com/problems/boolean-evaluation-lcci/solution/zi-xia-er-shang-de-qu-jian-dp-by-justbruteforce/
一个大区间的1或0的个数取决于,所有该区间内以操作符分割的两个小区间的情况,将所有操作符划分情况加起来
dp[区间左端点][区间右端点][0或者1] ==> 该区间内结果为0/1的次数
框架如下:
for(区间长度 = 1,3,5) // 即 1,1&1,1&1&1,,
----for(穷举每个区间,区间左端点为i = 0,1,2,,区间右断电为i + len - 1)
----------若区间长度为3,即[0,2] [1,3] [2,4]等,区间左闭右闭
--------------for(在每个区间内再穷举该区间内的所有操作符)
每个操作符将该区间划分成左右两个小的子区间(其小区间的结果都是之前求出来的)
将该区间内所有划分情况的结果求和,即为该区间的最后结果

class Solution {
    public int countEval(String s, int result) {
        int n = s.length();
        int[][][] dp = new int[n][n][2];
        for(int len = 1; len <= n; len += 2){//枚举区间长度 1 3 5 
            for(int i = 0; i + len - 1 < n; i += 2){ //区间左端点i 右端点i+len-1
                if(len == 1){
                    dp[i][i + len - 1][s.charAt(i) == '0' ? 0 : 1]++;
                }
                for(int j = i + 1; j < i + len - 1; j += 2){  //区间内操作符
                    char op = s.charAt(j);
                    switch(op){
                        case '&'://00&0 0&1 1&011&1
                            dp[i][i + len - 1][0] += dp[i][j - 1][0] * (dp[j + 1][i + len - 1][0] + dp[j + 1][i + len - 1][1]) +
                                                    dp[i][j - 1][1] * dp[j + 1][i + len - 1][0];
                            dp[i][i + len - 1][1] += dp[i][j - 1][1] * dp[j + 1][i + len - 1][1];
                            break;
                        case '|':
                            dp[i][i + len - 1][0] += dp[i][j - 1][0] * dp[j + 1][i + len - 1][0];
                            dp[i][i + len - 1][1] += dp[i][j - 1][0] * dp[j + 1][i + len - 1][1] +
                                                    dp[i][j - 1][1] * (dp[j + 1][i + len - 1][0] + dp[j + 1][i + len - 1][1]);
                            break;
                        case '^':
                            dp[i][i + len - 1][0] += dp[i][j - 1][0] * dp[j + 1][i + len - 1][0] + dp[i][j - 1][1] * dp[j + 1][i + len - 1][1];
                            dp[i][i + len - 1][1] += dp[i][j - 1][0] * dp[j + 1][i + len - 1][1] + dp[i][j - 1][1] * dp[j + 1][i + len - 1][0];
                            break;
                        default:
                            break;
                    }
                }
            }
        }
        return dp[0][n - 1][result];
    }
}

你可能感兴趣的:(leetcode,动态规划)