一、题目
给定一个布尔表达式和一个期望的布尔结果 result,布尔表达式由 0 (false)、1 (true)、& (AND)、 | (OR) 和 ^ (XOR) 符号组成。实现一个函数,算出有几种可使该表达式得出 result 值的括号方法。
二、题解
范围尝试模型
2.1 递归
public static class Info{
public int t;
public int f;
public Info(int t, int f) {
this.t = t;
this.f = f;
}
}
//L...R 一共有奇数个字符
//L和R位置的字符,非0即1
//返回str[L..R] 为true和false的方法数
public static Info func(char[] str,int L ,int R){
int t=0;
int f=0;
if(L==R){
t=str[L]=='1'?1:0;
f=str[L]=='0'?1:0;
} else {
//spilt是逻辑符号的位置
for (int spilt = L+1; spilt <R ; spilt+=2) {
Info left=func(str,L,spilt-1);
Info right=func(str,spilt+1,R);
int a=left.t;
int b=left.f;
int c=right.t;
int d=right.f;
switch (str[spilt]){
case '&':
t+=a*c;
f+=a*d+b*c+b*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;
}
}
}
return new Info(t,f);
}
public static int countEval1(String s, int result) {
if(s==null||s.length()==0){
return 0;
}
char[] str=s.toCharArray();
Info ret=func(str,0,str.length-1);
if(result==0){
return ret.f;
}else {
return ret.t;
}
}
2.2 记忆化搜索
在递归的基础上添加一个缓存表,避免重复计算
public static class Info{
public int t;
public int f;
public Info(int t, int f) {
this.t = t;
this.f = f;
}
}
public static Info func2(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){
t=str[L]=='1'?1:0;
f=str[L]=='0'?1:0;
} else {
for (int spilt = L+1; spilt <R ; spilt+=2) {
Info left=func2(str,L,spilt-1,dp);
Info right=func2(str,spilt+1,R,dp);
int a=left.t;
int b=left.f;
int c=right.t;
int d=right.f;
switch (str[spilt]){
case '&':
t+=a*c;
f+=a*d+b*c+b*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];
}
public static int countEval2(String s, int result) {
if(s==null||s.length()==0){
return 0;
}
char[] str=s.toCharArray();
int N=str.length;
Info[][] dp=new Info[N][N];
Info ret=func2(str,0,str.length-1,dp);
if(result==0){
return ret.f;
}else {
return ret.t;
}
}