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

福大大 答案2021-06-03:

方法一:递归。
方法二:动态规划。

代码用golang编写。代码如下:

package main

import "fmt"

func main() {

    express := "1&1&1"
    desired := 1
    ret0 := countEval0(express, desired)
    ret1 := countEval1(express, desired)
    ret2 := countEval2(express, desired)
    fmt.Println(ret0, ret1, ret2)

}

func countEval0(express string, desired int) int {
    if express == "" {
        return 0
    }
    N := len(express)
    dp := make([][]*Info, N)
    for i := 0; i < N; i++ {
        dp[i] = make([]*Info, N)
    }
    allInfo := ff(express, 0, len(express)-1, dp)
    return twoSelectOne(desired == 1, allInfo.t, allInfo.f)
}

type Info struct {
    t int
    f int
}

func twoSelectOne(c bool, a int, b int) int {
    if c {
        return a
    } else {
        return b
    }
}

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

func countEval1(express string, desired int) int {
    if express == "" {
        return 0
    }
    return f(express, desired, 0, len(express)-1)
}

func f(str string, desired int, L int, R int) int {
    if L == R {
        if str[L] == '1' {
            return desired
        } else {
            return desired ^ 1
        }
    }
    res := 0
    if desired == 1 {
        for i := L + 1; i < R; i += 2 {
            switch str[i] {
            case '&':
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                break
            case '|':
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                break
            case '^':
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                break
            }
        }
    } else {
        for i := L + 1; i < R; i += 2 {
            switch str[i] {
            case '&':
                res += f(str, 0, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 1, L, i-1) * f(str, 0, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            case '|':
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            case '^':
                res += f(str, 1, L, i-1) * f(str, 1, i+1, R)
                res += f(str, 0, L, i-1) * f(str, 0, i+1, R)
                break
            }
        }
    }
    return res
}

func countEval2(express string, desired int) int {
    if express == "" {
        return 0
    }
    N := len(express)
    dp := make([][][]int, 2)
    for i := 0; i < 2; i++ {
        dp[i] = make([][]int, N)
        for j := 0; j < N; j++ {
            dp[i][j] = make([]int, N)
        }
    }
    dp[0][0][0] = twoSelectOne(express[0] == '0', 1, 0)
    dp[1][0][0] = dp[0][0][0] ^ 1
    for i := 2; i < len(express); i += 2 {
        dp[0][i][i] = twoSelectOne(express[i] == '1', 0, 1)
        dp[1][i][i] = twoSelectOne(express[i] == '0', 0, 1)
        for j := i - 2; j >= 0; j -= 2 {
            for k := j; k < i; k += 2 {
                if express[k+1] == '&' {
                    dp[1][j][i] += dp[1][j][k] * dp[1][k+2][i]
                    dp[0][j][i] += (dp[0][j][k]+dp[1][j][k])*dp[0][k+2][i] + dp[0][j][k]*dp[1][k+2][i]
                } else if express[k+1] == '|' {
                    dp[1][j][i] += (dp[0][j][k]+dp[1][j][k])*dp[1][k+2][i] + dp[1][j][k]*dp[0][k+2][i]
                    dp[0][j][i] += dp[0][j][k] * dp[0][k+2][i]
                } else {
                    dp[1][j][i] += dp[0][j][k]*dp[1][k+2][i] + dp[1][j][k]*dp[0][k+2][i]
                    dp[0][j][i] += dp[0][j][k]*dp[0][k+2][i] + dp[1][j][k]*dp[1][k+2][i]
                }
            }
        }
    }
    return dp[desired][0][N-1]
}

执行结果如下:
图片


左神java代码