#1896
Hard Algorithms Minimum cost to change the final value of expression
Math String Dynamic Programming Stack
51.2% acceptance
Feb 25, 2026
248
43
Given a valid boolean expression as a string, return the minimum cost to change the final value. Operations: flip 0↔1 (cost 1) or flip &↔| (cost 1). No operator precedence except parentheses; evaluate left-to-right.
Solution
Rust
Time O(n)
Space O(n)
impl Solution {
pub fn min_operations_to_flip(expression: String) -> i32 {
// Stack of (value, cost_to_flip)
// value: current value of sub-expression
// cost: minimum cost to flip it
let mut stack: Vec<(i32, i32)> = Vec::new();
let mut op_stack: Vec<u8> = Vec::new(); // operators: b'&' or b'|'
let combine = |a: (i32, i32), b: (i32, i32), op: u8| -> (i32, i32) {
let (av, ac) = a;
let (bv, bc) = b;
if op == b'&' {
let val = av & bv;
let cost = if val == 1 {
// To flip to 0: flip either operand (min cost)
ac.min(bc)
} else {
// To flip to 1: if both 0, flip both or change op
if av == 1 || bv == 1 {
// one is 0, one is 1: flip the 0, or change & to |
if av == 0 { ac.min(1) } else { bc.min(1) }
} else {
// both are 0: flip one of them AND change op, or flip both
// change & to |: cost 1 + flip whichever side we want (but | of two 0s is still 0, so also need to flip one side) => actually if we change & to |, val becomes 0|0=0, still need to flip.
// Easiest: flip one side (cost min(ac,bc)) and change op (cost 1)? No.
// Actually: to get 1 from 0&0: options:
// - change & to | (cost 1): gives 0|0=0, still 0.
// - flip one 0->1 (cost min(ac,bc)): gives 1&0=0, still 0. Need to flip both OR flip one and change op.
// - flip both (cost ac+bc): gives 1&1=1
// - flip one and change op (cost min(ac,bc)+1): gives 1|0=1 or 0|1=1
(ac + bc).min(ac.min(bc) + 1)
}
};
(val, cost)
} else {
// op == '|'
let val = av | bv;
let cost = if val == 0 {
// To flip to 1: flip either
ac.min(bc)
} else {
if av == 0 || bv == 0 {
// one is 1, one is 0: change | to & costs 1, or flip the 1
if av == 1 { ac.min(1) } else { bc.min(1) }
} else {
// both 1: to get 0, need to flip both or flip one and change op
(ac + bc).min(ac.min(bc) + 1)
}
};
(val, cost)
}
};
for &b in expression.as_bytes() {
match b {
b'0' => stack.push((0, 1)),
b'1' => stack.push((1, 1)),
b'(' => op_stack.push(b'('),
b'&' | b'|' => op_stack.push(b),
b')' => {
// Pop the '(' from op_stack — the top of stack is result inside parens
op_stack.pop(); // remove '('
// If there's a pending operator, combine
if let Some(&op) = op_stack.last() {
if op == b'&' || op == b'|' {
op_stack.pop();
let b_val = stack.pop().unwrap();
let a_val = stack.pop().unwrap();
stack.push(combine(a_val, b_val, op));
}
}
}
_ => {}
}
// After pushing a value (0 or 1), check if we should combine
if b == b'0' || b == b'1' {
if let Some(&op) = op_stack.last() {
if op == b'&' || op == b'|' {
op_stack.pop();
let b_val = stack.pop().unwrap();
let a_val = stack.pop().unwrap();
stack.push(combine(a_val, b_val, op));
}
}
}
}
stack.pop().unwrap().1
}
}