<div>
Given a n * n matrix grid of 0's and 1's only. We want to represent the grid with a Quad-Tree.
Return the root of the Quad-Tree representing the grid.
Notice that you can assign the value of a node to True or False when isLeaf is False, and both are accepted in the answer.
A Quad-Tree is a tree data structure in which each internal node has exactly four children. Besides, each node has two attributes:
val: True if the node represents a grid of 1's or False if the node represents a grid of 0's.isLeaf: True if the node is leaf node on the tree or False if the node has the four children.
<pre>class Node { public boolean val; public boolean isLeaf; public Node topLeft; public Node topRight; public Node bottomLeft; public Node bottomRight; }</pre>
We can construct a Quad-Tree from a two-dimensional area using the following steps:
- If the current grid has the same value (i.e all
1'sor all0's) setisLeafTrue and setvalto the value of the grid and set the four children to Null and stop. - If the current grid has different values, set
isLeafto False and setvalto any value and divide the current grid into four sub-grids as shown in the photo. - Recurse for each of the children with the proper sub-grid.

If you want to know more about the Quad-Tree, you can refer to the wiki.
Quad-Tree format:
The output represents the serialized format of a Quad-Tree using level order traversal, where null signifies a path terminator where no node exists below.
It is very similar to the serialization of the binary tree. The only difference is that the node is represented as a list [isLeaf, val].
If the value of isLeaf or val is True we represent it as 1 in the list [isLeaf, val] and if the value of isLeaf or val is False we represent it as 0.
Example 1:

<pre>Input: grid = [[0,1],[1,0]]
Output: [[0,1],[1,0],[1,1],[1,1],[1,0]]
Explanation: The explanation of this example is shown below:
Notice that 0 represnts False and 1 represents True in the photo representing the Quad-Tree.
</pre>
Example 2:

<pre>Input: grid = [[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0],[1,1,1,1,0,0,0,0]]
Output: [[0,1],[1,1],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]]
Explanation: All values in the grid are not the same. We divide the grid into four sub-grids.
The topLeft, bottomLeft and bottomRight each has the same value.
The topRight have different values so we divide it into 4 sub-grids where each has the same value.
Explanation is shown in the photo below:
</pre>
Constraints:
n == grid.length == grid[i].lengthn == 2<sup>x</sup>where0 <= x <= 6
</div>
题目大意:
由矩阵建四叉树。矩阵有0和1组成。按以下步骤:若子矩阵(变成为2的幂)只含1或0,生成一个叶子节点,值为该值;子矩阵含0和1混合,值为0或1(均为答案),非叶子节点,递归四个同样大小的矩阵生成相应节点。
矩阵大小为2的幂,最小长度为1.
单格DFS算法II解题思路(推荐):
也是DFS,但递归终止条件为长度1,也就是每个cell都是叶子节点,先递归然后再归纳,若四个儿子节点都是叶子节点且值都相等,合并为一个叶子节点。否则为非叶子节点。 此算法实现更简单,但比较难想出。上述方法思想是按照题意。
注意事项:
- size = 1作为终止条件
- 两个条件该轮递归的节点为叶子节点,第一值相等,第二儿子节点都是叶子节点
Python代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def construct(self, grid: List[List[int]]) -> 'Node':
return self.dfs(grid, 0, 0, len(grid))
def dfs(self, grid, start_x, start_y, n):
if n == 1:
return Node(grid[start_x][start_y], True, None, None, None, None)
top_left = self.dfs(grid, start_x, start_y, n // 2)
top_right = self.dfs(grid, start_x, start_y + n // 2, n // 2)
bottom_left = self.dfs(grid, start_x + n // 2, start_y, n // 2)
bottom_right = self.dfs(grid, start_x + n // 2, start_y + n // 2, n // 2)
if top_left.val == top_right.val == bottom_left.val == bottom_right.val and \
top_left.isLeaf and top_right.isLeaf and bottom_left.isLeaf and bottom_right.isLeaf: # remmember
return Node(top_left.val, True, None, None, None, None)
else:
return Node(1, False, top_left, top_right, bottom_left, bottom_right)
算法分析:
时间复杂度为<code>O(n<sup>2</sup>)</code>,空间复杂度O(1)`
presum解题思路(不推荐):
这是我的方法,按照定义求解,定义是递归的,所以用DFS。而统计子矩阵和用presum提高效率。但实现比较复杂
解题步骤:
N/A
注意事项:
- 子矩阵presum用模板
- 终止条件为子矩阵sum是0或n平方
Python代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34def construct(self, grid: List[List[int]]) -> 'Node':
presum = self.get_presum(grid)
return self.dfs(grid, (0, 0), (len(grid) - 1, len(grid[0]) - 1), presum)
def dfs(self, grid, top_left, bottom_right, presum):
grim_sum = self.get_grid_sum(top_left, bottom_right, presum)
if grim_sum == 0:
return Node(0, True, None, None, None, None)
if grim_sum == (bottom_right[0] - top_left[0] + 1) * (bottom_right[0] - top_left[0] + 1):
return Node(1, True, None, None, None, None)
node = Node(1, False, None, None, None, None)
row_mid = top_left[0] + (bottom_right[0] - top_left[0]) // 2
col_mid = top_left[1] + (bottom_right[1] - top_left[1]) // 2
node.topLeft = self.dfs(grid, top_left, (row_mid, col_mid), presum)
node.topRight = self.dfs(grid, (top_left[0], col_mid + 1), (row_mid, bottom_right[1]), presum)
node.bottomLeft = self.dfs(grid, (row_mid + 1, top_left[1]), (bottom_right[0], col_mid), presum)
node.bottomRight = self.dfs(grid, (row_mid + 1, col_mid + 1), bottom_right, presum)
return node
def get_grid_sum(self, top_left, bottom_right, presum):
left = 0 if top_left[1] < 1 else presum[bottom_right[0]][top_left[1] - 1]
top = 0 if top_left[0] < 1 else presum[top_left[0] - 1][bottom_right[1]]
diag = 0 if top_left[0] < 1 or top_left[1] < 1 else presum[top_left[0] - 1][top_left[1] - 1]
return presum[bottom_right[0]][bottom_right[1]] - left - top + diag
def get_presum(self, grid):
presum = [[0 for _ in range(len(grid[0]))] for _ in range(len(grid))]
for i in range(len(grid)):
row_sum = 0
for j in range(len(grid[0])):
row_sum += grid[i][j]
presum[i][j] = row_sum + (presum[i - 1][j] if i > 0 else 0)
return presum
算法分析:
时间复杂度为<code>O(n<sup>2</sup>)</code>`,空间复杂度<code>O(n<sup>2</sup>)</code>


