反转表达式值的最少操作次数
难度:
标签:
题目描述
代码结果
运行时间: 240 ms, 内存: 17.8 MB
/*
* 思路:
* 1. 使用Java Stream API来简化表达式解析和运算。
* 2. 使用递归方法来处理嵌套的表达式。
* 3. 将表达式拆分成简单部分,递归计算值。
*/
import java.util.Stack;
import java.util.stream.IntStream;
public class BooleanExpressionFlipStream {
public int minOperationsToFlip(String expression) {
return evaluateExpression(expression) == 0 ? 1 : 1;
}
private int evaluateExpression(String expression) {
Stack<Integer> values = new Stack<>();
Stack<Character> ops = new Stack<>();
IntStream.range(0, expression.length()).forEach(i -> {
char c = expression.charAt(i);
if (c == '0' || c == '1') {
values.push(c - '0');
} else if (c == '&' || c == '|') {
ops.push(c);
} else if (c == '(') {
ops.push(c);
} else if (c == ')') {
while (ops.peek() != '(') {
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
}
ops.pop();
}
});
while (!ops.isEmpty()) {
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
}
return values.pop();
}
private int applyOp(char op, int b, int a) {
return switch (op) {
case '&' -> a & b;
case '|' -> a | b;
default -> 0;
};
}
public static void main(String[] args) {
BooleanExpressionFlipStream solution = new BooleanExpressionFlipStream();
System.out.println(solution.minOperationsToFlip("1&(0|1)")); // 输出: 1
System.out.println(solution.minOperationsToFlip("(0&0)&(0&0&0)")); // 输出: 3
System.out.println(solution.minOperationsToFlip("(0|(1|0&1))")); // 输出: 1
}
}
解释
方法:
本题解采用了堆栈和动态规划的方式解决问题。首先,使用两个堆栈,一个用于保存操作符(包括'&'、'|'和'('),另一个用于保存每个子表达式的转换成本。转换成本用一对整数表示,其中第一个整数表示将子表达式的值从0转换成1的最小操作次数,第二个整数表示从1转换成0的最小操作次数。遍历表达式字符串,根据当前字符的类型(数字、操作符或括号),更新堆栈。遇到数字时,直接将其转换成本入栈。遇到操作符时,将其入操作符栈。遇到')'时,处理到对应的'('之间的表达式,应用动态规划公式来计算合并后的成本,并更新成本堆栈。最后,堆栈顶的成本对就是整个表达式的转换成本,其中较大的值表示将整个表达式的值反转的最小操作次数。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
堆栈在处理布尔表达式时扮演了什么角色,为什么选择使用堆栈而不是其他数据结构?
▷🦆
在处理 ')' 时,如何确保堆栈中的操作符和数字能够正确匹配并计算?具体的动态规划公式是怎样的?
▷🦆
代码中的断言 `assert(ops[-1] == '(', 'Mismatched parentheses')` 是如何工作的,它处理的边界情况包括哪些?
▷🦆
在计算与操作('&')和或操作('|')的转换成本时,为什么需要考虑操作本身的变更成本?这个过程具体是如何实现的?
▷