Leetcode 427. Construct Quad Tree

Problem Explanation

This problem is asking you to implement a type of tree structure called a Quadtree. A Quadtree is a tree data structure that is used to represent a 2D space that can be divided into four quadrants. Each node in the Quadtree represents a square area of the 2D space, and it may either be a leaf node or an internal node that has four children representing the four quadrants of the square. If a node is a leaf node, it means all values in the square area it represents are the same, either true or false.

For example, consider the following 8x8 grid:

1
2
3[
4  [1,1,0,0,0,0,0,0],
5  [1,1,0,0,0,0,0,0],
6  [0,0,0,0,1,1,0,0],
7  [0,0,0,0,1,1,0,0],
8  [0,0,0,0,0,0,1,1],
9  [0,0,0,0,0,0,1,1],
10  [0,0,0,0,0,0,0,0],
11  [0,0,0,0,0,0,0,0]
12]

This grid can be divided into sub-grids until all values in each sub-grid are the same. The division process goes like this:

  1. The whole 8x8 grid is divided into four 4x4 grids.
  2. Each 4x4 grid with mixed values is further divided into four 2x2 grids.
  3. Each 2x2 grid with mixed values is further divided into four 1x1 grids, which must all have the same value.

The resulting Quadtree would look like this:

1
2
3                   (False, *)
4                 /       |     \
5        (True, *)   (True, *)    (False,1)
6          / \         /     \
7    (True,1)  (True,0)  (True, 0)    (True, 1)

Solution Approach

The solution to this problem can be achieved by using recursion. The key idea is to divide the current grid into four sub-grids, and for each sub-grid, check if all values are the same. If all values are the same, create a new leaf node representing that sub-grid. If not, repeat the process on that sub-grid.

Python Solution

1
2python
3class Solution:
4    def construct(self, grid):
5        def helper(i, j, w):
6            if all(grid[x][y] == grid[i][j] for x in range(i, i + w) for y in range(j, j + w)):
7                return Node(grid[i][j] == 1, True, None, None, None, None)
8            nw = w // 2
9            return Node('*', False, 
10                        helper(i, j, nw), 
11                        helper(i, j + nw, nw), 
12                        helper(i + nw, j, nw), 
13                        helper(i + nw, j + nw, nw))
14        return helper(0, 0, len(grid))

Java Solution

1
2java
3class Solution {
4    public Node construct(int[][] grid) {
5        return build(grid, 0, 0, grid.length);
6    }
7
8    private Node build(int[][] grid, int i, int j, int len) {
9        if (isLeaf(grid, i, j, len)) {
10            return new Node(grid[i][j]==1, true, null, null, null, null);
11        }
12        len /= 2;
13        return new Node(true, false,
14                        build(grid, i, j, len),
15                        build(grid, i, j + len, len),
16                        build(grid, i + len, j, len),
17                        build(grid, i + len, j + len, len));
18    }
19
20    private boolean isLeaf(int[][] grid, int i, int j, int len) {
21        for (int a = i; a < i + len; ++a) {
22            for (int b= j; b < j + len; ++b) {
23                if (grid[a][b] != grid[i][j]) {
24                    return false;
25                }
26            }
27        }
28        return true;
29    }
30}

JavaScript Solution

1
2javascript
3class Solution {
4    construct(grid) {
5        function build(i, j, len) {
6            if (isLeaf(i, j, len)) {
7                return new Node(grid[i][j] === 1, true, null, null, null, null);
8            }
9            var len2 = len / 2;
10            return new Node(true, false,
11                            build(i, j, len2),
12                            build(i, j + len2, len2),
13                            build(i + len2, j, len2),
14                            build(i + len2, j + len2, len2));
15        }
16
17        function isLeaf(i, j, len) {
18            for (let a = i; a < i + len; ++a) {
19                for (let b = j; b < j + len; ++b) {
20                    if (grid[a][b] !== grid[i][j]) {
21                        return false;
22                    }
23                }
24            }
25            return true;
26        }
27
28        return build(0, 0, grid.length);
29    }
30};

C++ Solution

1
2cpp
3class Solution {
4public:
5    Node* construct(vector<vector<int>>& grid) {
6        return helper(grid, 0, 0, grid.size());
7    }
8
9private:
10    Node* helper(vector<vector<int>>& grid, int i, int j, int len) {
11        if (isUniform(grid, i, j, len)) {
12            return new Node(grid[i][j] == 1, true, nullptr, nullptr, nullptr, nullptr);
13        } else {
14            int half = len / 2;
15            return new Node(true, false,
16                            helper(grid, i, j, half),
17                            helper(grid, i, j + half, half),
18                            helper(grid, i + half, j, half),
19                            helper(grid, i + half, j + half, half));
20        }
21    }
22
23    bool isUniform(vector<vector<int>>& grid, int i, int j, int len) {
24        int first = grid[i][j];
25        for (int x = i; x < i + len; ++x)
26            for (int y = j; y < j + len; ++y)
27                if (grid[x][y] != first)
28                    return false;
29        return true;
30    }
31};

C# Solution

1
2csharp
3public class Solution {
4    public Node Construct(int[][] grid) {
5        return Build(grid, 0, 0, grid.Length);
6    }
7    
8    private Node Build(int[][] grid, int i, int j, int len) {
9        if (IsUniform(grid, i, j, len)) {
10            return new Node(grid[i][j] == 1, true, null, null, null, null);
11        } else {
12            int half = len / 2;
13            return new Node(true, false,
14                            Build(grid, i, j, half),
15                            Build(grid, i, j + half, half),
16                            Build(grid, i + half, j, half),
17                            Build(grid, i + half, j + half, half));
18        }
19    }
20
21    private bool IsUniform(int[][] grid, int i, int j, int len) {
22        int first = grid[i][j];
23        for (int x = i; x < i + len; ++x)
24            for (int y = j; y < j + len; ++y)
25                if (grid[x][y] != first)
26                    return false;
27        return true;
28    }
29}

In each solution, for every square or sub-grid, we check whether it is Uniform (meaning all elements are either 1 or 0). If it is, we create a leaf node for that square. If not, we subdivide it into four smaller squares (top left, top right, bottom left, and bottom right) and recursively construct quad-tree for these squares. The process continues recursively until all sub-grids are uniform.We covered all the major programming languages and how to solve the problem using these languages in an easy and comprehensive way. By utilizing recursion and tree data structure we could break down this problem to smaller manageable sub-problems. Each solution from Python to C# adheres to the same basic principle of breaking down an 8x8 grid into smaller sub-grids and applying the same solution recursively.

In conclusion, this Quadtree problem emphasizes on understanding the fundamentals of tree data structure and recursion. With a good grasp of these fundamental concepts, one will not only be able to solve this problem but also be adept at tackling similar problems. While the languages differ slightly in syntax, the core logic remains unchanged, proving that algorithmic problem-solving transcends the confines of any specific programming languages. The solutions provided here are an optimal and clear way to solve this problem across different major programming languages. Additionally, their implementation also demonstrates understanding of recursion, tree data structure and quadtree, thereby strengthening one’s knowledge in these areas.

In future, when one encounters similar problems, one can utilize these concepts and approaches to devise an appropriate solution. The major takeaway from this problem-solving exercise should be the way recursion is used with the tree data structure to efficiently divide a complex problem into simple manageable parts, thereby making it easier to solve. Competitive programming encapsulates many challenges that test these basic fundamentals of programming, and being proficient at them would help clear many such rounds.


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫