427.Construct Quad Tree
===
###### tags: `Medium`,`Array`,`Divide and Conquer`,`Tree`,`Matrix`
[427. Construct Quad Tree](https://leetcode.com/problems/construct-quad-tree/)
### 題目描述
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.
```
class Node {
public boolean val;
public boolean isLeaf;
public Node topLeft;
public Node topRight;
public Node bottomLeft;
public Node bottomRight;
}
```
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's` or all `0's`) set `isLeaf` True and set `val` to the value of the grid and set the four children to Null and stop.
If the current grid has different values, set `isLeaf` to False and set `val` to 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.
![reference link](https://assets.leetcode.com/uploads/2020/02/11/new_top.png)
If you want to know more about the Quad-Tree, you can refer to the [wiki](https://en.wikipedia.org/wiki/Quadtree).
**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:**
![](https://assets.leetcode.com/uploads/2020/02/11/grid1.png)
```
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.
```
![](https://assets.leetcode.com/uploads/2020/02/12/e1tree.png)
**Example 2:**
![](https://assets.leetcode.com/uploads/2020/02/12/e2mat.png)
```
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:
```
![](https://assets.leetcode.com/uploads/2020/02/12/e2tree.png)
**Constraints**:
* `n` == `grid.length` == `grid[i].length`
* `n` == 2^x^ where 0 <= `x` <= 6
### 解答
#### C++
##### 思路:
1. 把2d array分成四個區塊來做Quad-tree, 某一個區塊若值都相同, 則val=該值, leaf為true, 不同則leaf為false, val可隨意填, 且還要進一步去再細分四個區塊, 直到所有leaf node的leaf值為true
2. 遞迴建構樹, 確認目前區塊值是否全一致, 一致則返回, 不一致繼續遞迴
```cpp=
class Solution {
public:
Node* helper(vector<vector<int>>& grid, int row, int col, int n)
{
bool is_same = true;
for(int i = row; i < row+n; i++)
{
for(int j = col; j < col+n; j++)
{
if(grid[i][j] != grid[row][col])
{
is_same = false;
break;
}
}
}
if(is_same)
return new Node(grid[row][col], true);
else
{
Node* cur_node = new Node(0, false);
n /= 2;
cur_node->topLeft = helper(grid, row, col, n);
cur_node->topRight = helper(grid, row, col+n, n);
cur_node->bottomLeft = helper(grid, row+n, col, n);
cur_node->bottomRight = helper(grid, row+n, col+n, n);
return cur_node;
}
}
Node* construct(vector<vector<int>>& grid) {
return helper(grid, 0, 0, grid.size());
}
};
```
Time: $O(n^2*logn)$ 每次確認n*n區塊內是否全相同, 最多做$logn$次
Extra Space: $O(n^2)$
> [name=XD] [time= Feb 27, 2023]
##### 思路
將leaf獨立出來,然後利用遞迴,只需要檢查四個孩子是否相同就好。
```cpp=
Node* zero = new Node(false, true);
Node* one = new Node(true, true);
class Solution {
public:
Node* dfs(vector<vector<int>>& grid, int i, int j, int n) {
if (n == 0) return grid[i][j] == 0 ? zero : one;
auto topLeft = dfs(grid, i, j, n >> 1);
auto topRight = dfs(grid, i, j + n, n >> 1);
auto bottomLeft = dfs(grid, i + n, j, n >> 1);
auto bottomRight = dfs(grid, i + n, j + n, n >> 1);
if (topLeft == topRight && bottomLeft == bottomRight && topLeft == bottomLeft) {
return topLeft;
}
return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight);
}
Node* construct(vector<vector<int>>& grid) {
return dfs(grid, 0, 0, grid.size() >> 1);
}
};
```
Time: $O(n^2)$
Space: $O(\log n)$
> [name=Yen-Chi Chen][time=Mon, Feb 27, 2023]
#### Python
```python=
class Solution:
def construct(self, grid: List[List[int]]) -> 'Node':
zero = Node(False, True, None, None, None, None)
one = Node(True, True, None, None, None, None)
def dfs(i, j, n):
if n == 0: return zero if grid[i][j] == 0 else one
tl = dfs(i, j, n >> 1)
tr = dfs(i, j + n, n >> 1)
bl = dfs(i + n, j, n >> 1)
br = dfs(i + n, j + n, n >> 1)
if tl == tr == bl == br:
return tl
return Node(False, False, tl, tr, bl, br)
return dfs(0, 0, len(grid) >> 1)
```
> [name=Yen-Chi Chen][time=Mon, Feb 27, 2023]
### Reference
[回到題目列表](https://hackmd.io/@Marsgoat/leetcode_every_day)