面试题 08.14:布尔运算

简介: 面试题 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

解题

方法一:动态规划

严格来说这个答案不是动态规划。是分治,利用dp数组,记录之前访问过的结果。

参考链接1

参考链接2

image

k+=2是因,0或1 和 位运算符是 间隔出现的。

保证每次k出现都是数字0或1,每次k+1都是位运算符。

同时k

image

class Solution {
private:
    vector<vector<vector<int>>> dp;
    string s;
    int dfs(int start,int end,int result){
        if(start==end) return s[start]-'0'==result?1:0;
        if(dp[start][end][result]!=-1)return dp[start][end][result];//记忆化,防止重复访问
        int count=0;
        for(int k=start;k<end;k+=2){
            char op=s[k+1];
            for(int i=0;i<=1;i++){//00、01、10、11四种情况的和
                for(int j=0;j<=1;j++){
                    if(getBoolAns(i,j,op)==result){
                        count+=dfs(start,k,i)*dfs(k+2,end,j);
                    }
                }
            }
        }
        dp[start][end][result]=count;
        return count;
    }
    int getBoolAns(int val1,int val2,char op){
        if(op=='&') return val1&val2;
        if(op=='|') return val1|val2;
        if(op=='^') return val1^val2;
        return val1&val2;
    }
public:
    int countEval(string s, int result) {
        this->s=s;
        int n=s.size();
        dp=vector<vector<vector<int>>>(n,vector<vector<int>>(n,vector<int>(2,-1)));
        return dfs(0,n-1,result);
    }
};

换种写法

class Solution {
public:
    int countEval(string s, int result) {
        int n=s.size();
        vector<vector<vector<int>>> dp(n,vector<vector<int>>(n,vector<int>(2,-1)));
        function<bool(int,int,char)> getBoolAns=[&](int val1,int val2,char op){
            if(op=='^') return val1^val2;
            if(op=='|') return val1|val2;
            if(op=='&') return val1&val2;
            return val1&val2;
        };
        function<int(int,int,int)> dfs=[&](int start,int end,int r){
            if(start==end) return s[start]-'0'==r?1:0;
            if(dp[start][end][r]!=-1) return dp[start][end][r];
            int count=0;
            for(int k=start;k<end;k+=2){
                char op=s[k+1];
                for(int i=0;i<=1;i++){
                    for(int j=0;j<=1;j++){
                        if(getBoolAns(i,j,op)==r){
                            count+=dfs(start,k,i)*dfs(k+2,end,j);
                        }
                    }
                }
            }
            dp[start][end][r]=count;
            return count;
        };
        return dfs(0,n-1,result);
    }
};



相关文章
|
1月前
|
C语言
C语言操作符逻辑与,逻辑或面试真题(2)
C语言操作符逻辑与,逻辑或面试真题(2)
|
8月前
|
编译器 C语言 C++
【刷题笔记】Day1:操作符的使用和算术转换(下)
【刷题笔记】Day1:操作符的使用和算术转换(下)
|
8月前
【刷题笔记】Day1:操作符的使用和算术转换(上)
【刷题笔记】Day1:操作符的使用和算术转换(上)
|
1月前
|
存储 算法 C语言
C语言编程—中缀表达式转换为后缀表达式
1.创建栈 2.从左向右顺序获取中缀表达式 a.数字直接输出 b.运算符 情况一:遇到左括号直接入栈,遇到右括号将栈中左括号之后入栈的运算符全部弹栈输出,同时左括号出栈但是不输出。 情况二:遇到乘号和除号直接入栈,直到遇到优先级比它更低的运算符,依次弹栈。 情况三:遇到加号和减号,如果此时栈空,则直接入栈,否则,将栈中优先级高的运算符依次弹栈(注意:加号和减号属于同一个优先级,所以也依次弹栈)直到栈空或则遇到左括号为止,停止弹栈。(因为左括号要匹配右括号时才弹出)。 情况四:获取完后,将栈中剩余的运算符号依次弹栈输出 例:将:2*(9+6/3-5)+4转化为后缀表达式 2 9
52 0
|
4天前
|
算法 C语言
【C语言】:巧用移位操作符,位操作符解决问题
【C语言】:巧用移位操作符,位操作符解决问题
7 0
|
1月前
|
索引
【力扣刷题】数组实现栈、后缀表达式(逆波兰表达式)求值、中缀表达式转换为后缀表达式(无括号&&有括号)
【力扣刷题】数组实现栈、后缀表达式(逆波兰表达式)求值、中缀表达式转换为后缀表达式(无括号&&有括号)
22 0
|
1月前
|
存储 编译器
有趣的移位操作符和位操作符(由浅入深轻松搞定!)
有趣的移位操作符和位操作符(由浅入深轻松搞定!)
|
11月前
|
编译器 C语言 C++
操作符习题
操作符习题
剑指Offer - 面试题1:赋值运算符函数
剑指Offer - 面试题1:赋值运算符函数
35 0
|
C语言
C语言刷题系列——12.判断回文字符串
C语言刷题系列——12.判断回文字符串
136 0