Construct Quad Tree
Medium · Arrays & Hashing · Explanation and code example
Recursion (Space Optimized)
How it works
We can optimize memory by reusing leaf nodes. Since all leaves with value true are identical and all leaves with value false are identical, we can create just two singleton leaf nodes and reuse them throughout the tree instead of creating new leaf nodes each time.
Steps
- Create two shared leaf nodes: one for
falseand one fortrue. - Define
dfs(n, r, c)as before. - Base case: if
n == 1, return the appropriate shared leaf node based ongrid[r][c]. - Recursively build the four quadrants.
- If all four children are leaves with the same value, return one of the children (they point to the same shared node).
- Otherwise, return a new non-leaf node with the four children.
Complexity
- Time complexity:
O(n ^ 2) - Space complexity:
O(log n)for recursion stack.
Things to watch for
Confusing Row and Column Offsets When Dividing Quadrants
When dividing the grid into four quadrants, the top-left stays at (r, c), but the other three quadrants need correct offsets. A common mistake is swapping row and column increments.
Forgetting to Check All Four Children Are Leaves Before Merging
When merging four children into a single leaf node, you must verify that all four children are leaves AND have the same value. Checking only the values without confirming they are leaves will incorrectly merge non-leaf nodes.
Using Wrong Grid Size for Recursion
When dividing the grid, the new size should be n // 2, not n - 1 or any other calculation. Each level of recursion should exactly halve the region size since the grid dimension is always a power of 2.
Python code example
from typing import List
"""
# Definition for a QuadTree node.
class Node:
def __init__(self, val=False, isLeaf=False, topLeft=None, topRight=None, bottomLeft=None, bottomRight=None):
self.val = val
self.isLeaf = isLeaf
self.topLeft = topLeft
self.topRight = topRight
self.bottomLeft = bottomLeft
self.bottomRight = bottomRight
"""
class Solution:
def construct(self, grid: List[List[int]]) -> 'Node':
leafNodes = {
0: Node(False, True),
1: Node(True, True)
}
def dfs(n, r, c):
if n == 1:
return leafNodes[grid[r][c]]
n //= 2
topLeft = dfs(n, r, c)
topRight = dfs(n, r, c + n)
bottomLeft = dfs(n, r + n, c)
bottomRight = dfs(n, r + n, c + n)
if (topLeft.isLeaf and topRight.isLeaf and
bottomLeft.isLeaf and bottomRight.isLeaf and
topLeft.val == topRight.val == bottomLeft.val == bottomRight.val):
return topLeft
return Node(False, False, topLeft, topRight, bottomLeft, bottomRight)
return dfs(len(grid), 0, 0)
C++ code example
/*
// Definition for a QuadTree node.
class Node {
public:
bool val;
bool isLeaf;
Node* topLeft;
Node* topRight;
Node* bottomLeft;
Node* bottomRight;
Node() {
val = false;
isLeaf = false;
topLeft = NULL;
topRight = NULL;
bottomLeft = NULL;
bottomRight = NULL;
}
Node(bool _val, bool _isLeaf) {
val = _val;
isLeaf = _isLeaf;
topLeft = NULL;
topRight = NULL;
bottomLeft = NULL;
bottomRight = NULL;
}
Node(bool _val, bool _isLeaf, Node* _topLeft, Node* _topRight, Node* _bottomLeft, Node* _bottomRight) {
val = _val;
isLeaf = _isLeaf;
topLeft = _topLeft;
topRight = _topRight;
bottomLeft = _bottomLeft;
bottomRight = _bottomRight;
}
};
*/
class Solution {
private:
Node* falseLeaf = new Node(false, true);
Node* trueLeaf = new Node(true, true);
public:
Node* construct(vector<vector<int>>& grid) {
return dfs(grid, grid.size(), 0, 0);
}
private:
Node* dfs(vector<vector<int>>& grid, int n, int r, int c) {
if (n == 1) {
return grid[r][c] == 1 ? trueLeaf : falseLeaf;
}
n /= 2;
Node* topLeft = dfs(grid, n, r, c);
Node* topRight = dfs(grid, n, r, c + n);
Node* bottomLeft = dfs(grid, n, r + n, c);
Node* bottomRight = dfs(grid, n, r + n, c + n);
if (topLeft->isLeaf && topRight->isLeaf &&
bottomLeft->isLeaf && bottomRight->isLeaf &&
topLeft->val == topRight->val && topLeft->val == bottomLeft->val &&
topLeft->val == bottomRight->val) {
return topLeft;
}
return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight);
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.