LeetCode 558: Logical OR of Two Binary Grids Represented as Quad-Trees Solution in Python – A Step-by-Step Guide
Imagine you’re tasked with combining two binary grids—like two maps of 1s and 0s—using a logical OR operation, but instead of flat arrays, they’re cleverly compressed into quad-trees, and your job is to merge them into a single quad-tree representing the OR result, such as blending two 4x4 grids into one efficient structure. That’s the fascinating challenge of LeetCode 558: Logical OR of Two Binary Grids Represented as Quad-Trees, a medium-to-hard problem that’s a fantastic way to practice tree manipulation in Python. We’ll explore two solutions: the Best Solution, a recursive quad-tree merging that’s efficient and elegant, and an Alternative Solution, a brute-force grid reconstruction that’s straightforward but less optimized. With detailed examples, clear code, and a friendly tone—especially for the recursive approach—this guide will help you merge those grids, whether you’re new to coding or leveling up. Let’s blend those quad-trees and start merging!
What Is LeetCode 558: Logical OR of Two Binary Grids Represented as Quad-Trees?
In LeetCode 558: Logical OR of Two Binary Grids Represented as Quad-Trees, you’re given two quad-trees quadTree1 and quadTree2, each representing an n x n binary grid (n is a power of 2), where each node is either a leaf (with a value of 0 or 1) or an internal node with four children (top-left, top-right, bottom-left, bottom-right). Your task is to return a quad-tree representing the logical OR of the two grids, where OR combines 0s and 1s (0 OR 0 = 0, 1 OR anything = 1). For example, merging two simple quad-trees might compress a grid like [[1,1,0,0],[1,1,0,0],[0,0,1,1],[0,0,1,1]] with another into a new quad-tree. This problem builds on LeetCode 427: Construct Quad Tree but focuses on merging operations.
Problem Statement
- Input: quadTree1, quadTree2 (Node)—two quad-trees representing binary grids.
- Output: Node—quad-tree representing logical OR of the grids.
- Rules: Leaf nodes have value 0 or 1; internal nodes have 4 children; OR operation applies to corresponding grid cells.
Constraints
- quadTree1 and quadTree2 represent n x n grids (n = 2^k, 0 ≤ k ≤ 9).
- Leaf nodes have isLeaf = True, value 0 or 1.
- Internal nodes have isLeaf = False, four child nodes.
Examples
- Input:
- quadTree1: Leaf(1,1), quadTree2: Leaf(1,0)
- Output: Leaf(1,1)
- OR of two 1x1 grids: 1 OR 0 = 1.
- Input:
- quadTree1: Internal(0, [1,1,0,0]), quadTree2: Internal(0, [0,0,1,1])
- Output: Represents [[1,1,1,1],[1,1,1,1],[0,0,1,1],[0,0,1,1]]
- OR combines grids, may simplify to quad-tree.
- Input:
- quadTree1: Leaf(1,0), quadTree2: Leaf(1,1)
- Output: Leaf(1,1)
- 0 OR 1 = 1.
Understanding the Problem: Merging Quad-Trees
To solve LeetCode 558: Logical OR of Two Binary Grids Represented as Quad-Trees in Python, we need to merge two quad-trees into one that represents the logical OR of their corresponding binary grids. A quad-tree compresses a grid by dividing it into four quadrants, either as a leaf (uniform value) or an internal node (split into four subtrees). A naive approach might reconstruct the grids and OR them (O(n²)), but with n up to 2⁹ (512), recursive merging leverages the tree structure for efficiency. We’ll explore:
- Best Solution (Recursive Quad-Tree Merging): O(n) time, O(h) space (n = nodes, h = height)—efficient and elegant.
- Alternative Solution (Brute-Force Grid Reconstruction): O(n²) time, O(n²) space—simple but wasteful.
Let’s dive into the recursive solution with a friendly breakdown!
Best Solution: Recursive Quad-Tree Merging
Why Recursive Wins
The recursive quad-tree merging is the best for LeetCode 558 because it computes the OR result in O(n) time (n = total nodes) and O(h) space (h = tree height) by traversing both trees simultaneously, merging nodes based on their structure and values, and reconstructing a simplified quad-tree where possible. It’s like blending two tree-maps layer-by-layer, keeping the structure tidy and efficient!
How It Works
Think of this as a quad-tree blender:
- Step 1: Base Cases:
- Both leaves: OR their values, return new leaf if uniform.
- Step 2: Recursive Merge:
- If one is a leaf:
- If value 1, return it (1 OR anything = 1).
- If value 0, return other tree (0 OR x = x).
- If both internal:
- Recursively merge four child pairs.
- If all resulting children are leaves with same value, simplify to leaf.
- Step 3: Construct Result:
- Build new node with merged children or simplified leaf.
- Why It Works:
- Recursion handles tree structure naturally.
- Simplification reduces complexity where possible.
It’s like a quad-tree fusion master!
Step-by-Step Example
Example: quadTree1 = Leaf(1,1), quadTree2 = Leaf(1,0)
- Step 1: Both leaves.
- Step 2: OR values: 1 OR 0 = 1.
- Step 3: Return Leaf(1,1).
- Result: Leaf(1,1).
Example: quadTree1 = Internal(0, [1,1,0,0]), quadTree2 = Internal(0, [0,0,1,1])
- Grid Representation:
- quadTree1: [[1,1,0,0],[1,1,0,0],[0,0,0,0],[0,0,0,0]].
- quadTree2: [[0,0,0,0],[0,0,0,0],[1,1,1,1],[1,1,1,1]].
- Step 1: Both internal, merge children:
- TL: 1 OR 0 = 1.
- TR: 1 OR 0 = 1.
- BL: 0 OR 1 = 1.
- BR: 0 OR 1 = 1.
- Step 2: All children leaves with value 1, simplify.
- Result: Leaf(1,1).
Code with Detailed Line-by-Line Explanation
Here’s the Python code, explained for beginners:
class Node:
def __init__(self, isLeaf, val, topLeft, topRight, bottomLeft, bottomRight):
self.isLeaf = isLeaf
self.val = val
self.topLeft = topLeft
self.topRight = topRight
self.bottomLeft = bottomLeft
self.bottomRight = bottomRight
class Solution:
def intersect(self, quadTree1: 'Node', quadTree2: 'Node') -> 'Node':
# Step 1: Both leaves, compute OR
if quadTree1.isLeaf and quadTree2.isLeaf:
val = 1 if quadTree1.val == 1 or quadTree2.val == 1 else 0
return Node(True, val, None, None, None, None)
# Step 2: One leaf, handle based on value
if quadTree1.isLeaf:
return quadTree1 if quadTree1.val == 1 else quadTree2
if quadTree2.isLeaf:
return quadTree2 if quadTree2.val == 1 else quadTree1
# Step 3: Both internal, recursively merge children
tl = self.intersect(quadTree1.topLeft, quadTree2.topLeft)
tr = self.intersect(quadTree1.topRight, quadTree2.topRight)
bl = self.intersect(quadTree1.bottomLeft, quadTree2.bottomLeft)
br = self.intersect(quadTree1.bottomRight, quadTree2.bottomRight)
# Step 4: Simplify if all leaves with same value
if (tl.isLeaf and tr.isLeaf and bl.isLeaf and br.isLeaf and
tl.val == tr.val == bl.val == br.val):
return Node(True, tl.val, None, None, None, None)
# Step 5: Return internal node with merged children
return Node(False, 0, tl, tr, bl, br)
- Lines 13-15: Both leaves, OR values, return new leaf.
- Lines 18-21: One leaf, return 1-leaf or other tree.
- Lines 24-27: Recursively merge four child pairs.
- Lines 30-32: Simplify to leaf if all children uniform.
- Line 35: Return internal node with children.
- Time Complexity: O(n)—n nodes visited once.
- Space Complexity: O(h)—recursion stack (h ≤ log n).
It’s like a quad-tree merger!
Alternative Solution: Brute-Force Grid Reconstruction
Why an Alternative Approach?
The brute-force grid reconstruction converts both quad-trees to full grids, performs OR, and rebuilds a quad-tree, running in O(n²) time and O(n²) space (n = grid side length). It’s simple but wasteful, making it a good baseline for understanding or small grids.
How It Works
Picture this as a grid-rebuilding mixer:
- Step 1: Reconstruct grids from quad-trees.
- Step 2: OR corresponding cells.
- Step 3: Build new quad-tree from result.
- Step 4: Return quad-tree.
It’s like a grid-blending rebuilder!
Step-by-Step Example
Example: quadTree1 = Leaf(1,1), quadTree2 = Leaf(1,0)
- Step 1: Grids: [[1]], [[0]].
- Step 2: OR: [[1]].
- Step 3: Quad-tree: Leaf(1,1).
- Result: Leaf(1,1).
Code for Brute-Force Approach
class Solution:
def intersect(self, quadTree1: 'Node', quadTree2: 'Node') -> 'Node':
def to_grid(node, size, x=0, y=0):
grid = [[0] * size for _ in range(size)]
if node.isLeaf:
for i in range(x, x + size):
for j in range(y, y + size):
grid[i][j] = node.val
else:
half = size // 2
to_grid(node.topLeft, half, x, y)
to_grid(node.topRight, half, x, y + half)
to_grid(node.bottomLeft, half, x + half, y)
to_grid(node.bottomRight, half, x + half, y + half)
return grid
def build_quad(grid, size, x=0, y=0):
if size == 1:
return Node(True, grid[x][y], None, None, None, None)
half = size // 2
tl = build_quad(grid, half, x, y)
tr = build_quad(grid, half, x, y + half)
bl = build_quad(grid, half, x + half, y)
br = build_quad(grid, half, x + half, y + half)
if tl.isLeaf and tr.isLeaf and bl.isLeaf and br.isLeaf and tl.val == tr.val == bl.val == br.val:
return Node(True, tl.val, None, None, None, None)
return Node(False, 0, tl, tr, bl, br)
# Assume size from tree depth (e.g., 2^k)
size = 1
while size * size < sum(1 for _ in range(10)): # Simplified size calc
size *= 2
grid1 = to_grid(quadTree1, size)
grid2 = to_grid(quadTree2, size)
result_grid = [[grid1[i][j] | grid2[i][j] for j in range(size)] for i in range(size)]
return build_quad(result_grid, size)
- Lines 5-15: Convert quad-tree to grid.
- Lines 17-27: Build quad-tree from grid.
- Lines 31-36: Reconstruct grids, OR, rebuild.
- Time Complexity: O(n²)—grid operations.
- Space Complexity: O(n²)—grid storage.
It’s a grid-rebuilding mixer!
Comparing the Two Solutions
- Recursive (Best):
- Pros: O(n), O(h), efficient.
- Cons: Recursive logic.
- Brute-Force (Alternative):
- Pros: O(n²), O(n²), simple.
- Cons: Wasteful space/time.
Recursive wins for efficiency!
Additional Examples and Edge Cases
- Both 0-leaves: Leaf(1,0).
- Mixed grids: Handled by recursion.
- Single node: OR’d directly.
Recursive handles them all!
Complexity Recap
- Recursive: Time O(n), Space O(h).
- Brute-Force: Time O(n²), Space O(n²).
Recursive’s the efficiency champ!
Key Takeaways
- Recursive: Tree merging—learn at Python Basics!
- Brute-Force: Grid rebuild.
- Quad-Trees: OR is fun.
- Python: Recurse or brute, your pick!
Final Thoughts: Merge Those Grids!
LeetCode 558: Logical OR of Two Binary Grids Represented as Quad-Trees in Python is a clever tree challenge. Recursive quad-tree merging is your fast track, while brute-force offers a clear start. Want more? Try LeetCode 427: Construct Quad Tree or LeetCode 199: Binary Tree Right Side View. Ready to blend? Head to Solve LeetCode 558 on LeetCode and merge those quad-trees today!