{x}
blog image

Minimum Flips in Binary Tree to Get Result

Minimum Flips in Binary Tree to Get Result

This problem involves finding the minimum number of flips required in a binary tree's leaf nodes to achieve a desired boolean result at the root. The tree's nodes represent boolean operations (OR, AND, XOR, NOT) or boolean values (true/false).

Approach

The solution employs a post-order Depth-First Search (DFS) with dynamic programming. The DFS explores the tree from leaves to the root. For each node, it calculates two values:

  1. min_flips_false: The minimum number of flips needed to make the node evaluate to false.
  2. min_flips_true: The minimum number of flips needed to make the node evaluate to true.

These values are calculated recursively:

  • Leaf Nodes: For leaf nodes (0 or 1), min_flips_false is the node's value (0 if false, 1 if true), and min_flips_true is the opposite (1 if false, 0 if true).

  • Non-Leaf Nodes: For non-leaf nodes, the calculation depends on the operation:

    • OR (2): min_flips_false is the sum of min_flips_false of its children. min_flips_true is the minimum of three possibilities: flipping both children, flipping only the left, or flipping only the right.
    • AND (3): min_flips_true is the sum of min_flips_true of its children. min_flips_false is the minimum of three possibilities: flipping both children, flipping only the left, or flipping only the right.
    • XOR (4): min_flips_false is the minimum of two possibilities: flipping both children to have the same truth value or no flips, ensuring their truth values are different and result in false. min_flips_true is the minimum of flipping both children to make them different (result is true) or not flipping to make them different (result is true).
    • NOT (5): min_flips_true is the minimum of min_flips_false of its child and min_flips_true is the minimum of min_flips_true of its child.

Finally, the function returns either min_flips_false or min_flips_true based on the desired result.

Time and Space Complexity

  • Time Complexity: O(N), where N is the number of nodes in the tree. The DFS visits each node once.
  • Space Complexity: O(H), where H is the height of the tree. This is due to the recursive call stack in the DFS. In the worst case (a skewed tree), H could be N. In the average case, for balanced trees, H is log₂(N).

Code Explanation (Python)

class Solution:
    def minimumFlips(self, root: Optional[TreeNode], result: bool) -> int:
        def dfs(root: Optional[TreeNode]) -> (int, int):
            if root is None:
                return inf, inf  # Handle null children gracefully
            x = root.val
            if x in (0, 1): # Base case: leaf node
                return x, x ^ 1
            l, r = dfs(root.left), dfs(root.right) # Recursive calls on children
            if x == 2: # OR
                return l[0] + r[0], min(l[0] + r[1], l[1] + r[0], l[1] + r[1])
            if x == 3: # AND
                return min(l[0] + r[0], l[0] + r[1], l[1] + r[0]), l[1] + r[1]
            if x == 4: # XOR
                return min(l[0] + r[0], l[1] + r[1]), min(l[0] + r[1], l[1] + r[0])
            return min(l[1], r[1]), min(l[0], r[0]) # NOT
 
        return dfs(root)[int(result)] # Return the appropriate result based on the desired outcome
 

The other languages (Java, C++, Go, TypeScript) follow a similar logic, adapting the syntax and data structures to their respective languages. The core algorithm remains the same efficient post-order DFS with dynamic programming to minimize the number of flips.