#2313
Hard Algorithms Minimum flips in binary tree to get result
Dynamic Programming Tree Depth-First Search Binary Tree
56.8% acceptance
Mar 31, 2026
112
2
You are given the root of a binary tree with the following properties:
Leaf nodes have either the value 0 or 1, representing false and true respectively.
Non-leaf nodes have either the value 2, 3, 4, or 5, representing the boolean operations OR, AND, XOR, and NOT, respectively.
You are also given a boolean result, which is the desired result of the evaluation of the root node.
The evaluation of a node is as follows:
If the node is a leaf node, the evaluation is the value of the node, i.e. true or false.
Otherwise, evaluate the node's children and apply the boolean operation of its value with the children's evaluations.
In one operation, you can flip a leaf node, which causes a false node to become true, and a true node to become false.
Return the minimum number of operations that need to be performed such that the evaluation of root yields result. It can be shown that there is always a way to achieve result.
A leaf node is a node that has zero children.
Note: NOT nodes have either a left child or a right child, but other non-leaf nodes have both a left child and a right child.
Solution
Rust
Time O(n)
Space O(n)
// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
// pub val: i32,
// pub left: Option<Rc<RefCell<TreeNode>>>,
// pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//
// impl TreeNode {
// #[inline]
// pub fn new(val: i32) -> Self {
// TreeNode {
// val,
// left: None,
// right: None
// }
// }
// }
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
pub fn minimum_flips(root: Option<Rc<RefCell<TreeNode>>>, result: bool) -> i32 {
// DFS returns (cost_to_make_false, cost_to_make_true) for each node
fn dfs(node: &Option<Rc<RefCell<TreeNode>>>) -> (i32, i32) {
if let Some(n) = node {
let n = n.borrow();
match n.val {
0 => (0, 1), // leaf false: 0 to stay false, 1 to flip to true
1 => (1, 0), // leaf true: 1 to flip to false, 0 to stay true
2 => { // OR
let (lf, lt) = dfs(&n.left);
let (rf, rt) = dfs(&n.right);
// false: both children must be false
// true: at least one child must be true
(lf + rf, (lt + rf).min(lf + rt).min(lt + rt))
}
3 => { // AND
let (lf, lt) = dfs(&n.left);
let (rf, rt) = dfs(&n.right);
// false: at least one child must be false
// true: both children must be true
((lf + rf).min(lf + rt).min(lt + rf), lt + rt)
}
4 => { // XOR
let (lf, lt) = dfs(&n.left);
let (rf, rt) = dfs(&n.right);
// false: both same
// true: both different
((lf + rf).min(lt + rt), (lt + rf).min(lf + rt))
}
5 => { // NOT (has only one child)
let child = if n.left.is_some() { &n.left } else { &n.right };
let (cf, ct) = dfs(child);
(ct, cf)
}
_ => unreachable!(),
}
} else {
(0, 0)
}
}
let (cost_false, cost_true) = dfs(&root);
if result { cost_true } else { cost_false }
}
}