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 ofrootyieldsresult. 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.
Input: root =[3,5,4,2,null,1,1,1,0], result =trueOutput: 2Explanation:
It can be shown that a minimum of 2 nodes have to be flipped to make the root of the tree
evaluate to true. One way to achieve thisis shown in the diagram above.
Example 2:
1
2
3
4
Input: root =[0], result =falseOutput: 0Explanation:
The root of the tree already evaluates to false, so 0 nodes have to be flipped.
Constraints:
The number of nodes in the tree is in the range [1, 105].
We recursively compute the minimum flips needed for each subtree to achieve both True and False results. For each node, we consider all possible ways to flip its value or its children’s values to achieve the desired result, using the operation type at the node.
structTreeNode {
int val;
TreeNode *left, *right;
};
classSolution {
private: unordered_map<TreeNode*, array<int,2>> dp;
voiddfs(TreeNode* node) {
if (!node) return;
if (node->val ==0|| node->val ==1) {
dp[node][node->val] =0;
dp[node][1-node->val] =1;
return;
}
if (dp.count(node)) return;
// Process children first
if (node->left) dfs(node->left);
if (node->right) dfs(node->right);
dp[node] = {1e9, 1e9};
if (node->val ==2) { // OR
for (int a =0; a <2; ++a)
for (int b =0; b <2; ++b) {
int res = a | b;
dp[node][res] = min(dp[node][res], dp[node->left][a] + dp[node->right][b]);
}
} elseif (node->val ==3) { // AND
for (int a =0; a <2; ++a)
for (int b =0; b <2; ++b) {
int res = a & b;
dp[node][res] = min(dp[node][res], dp[node->left][a] + dp[node->right][b]);
}
} elseif (node->val ==4) { // XOR
for (int a =0; a <2; ++a)
for (int b =0; b <2; ++b) {
int res = a ^ b;
dp[node][res] = min(dp[node][res], dp[node->left][a] + dp[node->right][b]);
}
} elseif (node->val ==5) { // NOT
TreeNode* child = node->left ? node->left : node->right;
for (int a =0; a <2; ++a) {
int res =1- a;
dp[node][res] = min(dp[node][res], dp[child][a]);
}
}
}
public:int minimumFlips(TreeNode* root, bool result) {
dfs(root);
return dp[root][result];
}
};
classTreeNode(var `val`: Int) {
var left: TreeNode? = nullvar right: TreeNode? = null}
classSolution {
funminimumFlips(root: TreeNode?, result: Boolean): Int {
fundfs(node: TreeNode?): IntArray {
if (node ==null) {
return intArrayOf(0, 0)
}
// Leaf nodes
if (node.`val` ==0) {
return intArrayOf(0, 1) // [false_cost, true_cost]
}
if (node.`val` ==1) {
return intArrayOf(1, 0) // [false_cost, true_cost]
}
// Process children
val left = node.left?.let { dfs(it) }
val right = node.right?.let { dfs(it) }
val dp = intArrayOf(Int.MAX_VALUE, Int.MAX_VALUE)
when (node.`val`) {
2-> { // OR
for (a in0..1) {
for (b in0..1) {
val res = a or b
val cost = (left?.get(a) ?:0) + (right?.get(b) ?:0)
dp[res] = minOf(dp[res], cost)
}
}
}
3-> { // AND
for (a in0..1) {
for (b in0..1) {
val res = a and b
val cost = (left?.get(a) ?:0) + (right?.get(b) ?:0)
dp[res] = minOf(dp[res], cost)
}
}
}
4-> { // XOR
for (a in0..1) {
for (b in0..1) {
val res = a xor b
val cost = (left?.get(a) ?:0) + (right?.get(b) ?:0)
dp[res] = minOf(dp[res], cost)
}
}
}
5-> { // NOT
val child = left ?: right
for (a in0..1) {
val res = 1 - a
dp[res] = minOf(dp[res], child?.get(a) ?:0)
}
}
}
return dp
}
val res = dfs(root)
returnif (result) res[1] else res[0]
}
}
defminimum_flips(root: 'TreeNode', result: bool) -> int:
defdfs(node):
ifnot node:
return [0, 0]
if node.val ==0:
return [0, 1]
if node.val ==1:
return [1, 0]
left = dfs(node.left) if node.left elseNone right = dfs(node.right) if node.right elseNone dp = [float('inf'), float('inf')]
if node.val ==2: # ORfor a in range(2):
for b in range(2):
dp[a|b] = min(dp[a|b], left[a] + right[b])
elif node.val ==3: # ANDfor a in range(2):
for b in range(2):
dp[a&b] = min(dp[a&b], left[a] + right[b])
elif node.val ==4: # XORfor a in range(2):
for b in range(2):
dp[a^b] = min(dp[a^b], left[a] + right[b])
elif node.val ==5: # NOTfor a in range(2):
dp[1-a] = min(dp[1-a], (left if left else right)[a])
##### Rust
use std::rc::Rc;
use std::cell::RefCell;
#[derive(Debug, PartialEq, Eq)]pubstructTreeNode {
pub val: i32,
pub left: Option<Rc<RefCell<TreeNode>>>,
pub right: Option<Rc<RefCell<TreeNode>>>,
}
impl Solution {
pubfnminimum_flips(root: Option<Rc<RefCell<TreeNode>>>, result: bool) -> i32 {
fndfs(node: &Option<Rc<RefCell<TreeNode>>>) -> [i32; 2] {
iflet Some(n) = node {
let n = n.borrow();
// Leaf nodes
if n.val ==0 {
return [0, 1]; // [false_cost, true_cost]
}
if n.val ==1 {
return [1, 0]; // [false_cost, true_cost]
}
// Process children
let left =if n.left.is_some() { dfs(&n.left) } else { [0, 0] };
let right =if n.right.is_some() { dfs(&n.right) } else { [0, 0] };
letmut dp = [i32::MAX, i32::MAX];
match n.val {
2=> { // OR
for a in0..2 {
for b in0..2 {
let res = (a | b) asusize;
let cost = left[a] + right[b];
dp[res] = dp[res].min(cost);
}
}
}
3=> { // AND
for a in0..2 {
for b in0..2 {
let res = (a & b) asusize;
let cost = left[a] + right[b];
dp[res] = dp[res].min(cost);
}
}
}
4=> { // XOR
for a in0..2 {
for b in0..2 {
let res = (a ^ b) asusize;
let cost = left[a] + right[b];
dp[res] = dp[res].min(cost);
}
}
}
5=> { // NOT
let child =if n.left.is_some() { left } else { right };
for a in0..2 {
let res = (1- a) asusize;
dp[res] = dp[res].min(child[a]);
}
}
_ => {}
}
dp
} else {
[0, 0]
}
}
let res = dfs(&root);
if result { res[1] } else { res[0] }
}
}