|
| 1 | +[](https://github.com/LeetCode-in-Net/LeetCode-in-Net) |
| 2 | +[](https://github.com/LeetCode-in-Net/LeetCode-in-Net/fork) |
| 3 | + |
| 4 | +## 427\. Construct Quad Tree |
| 5 | + |
| 6 | +Medium |
| 7 | + |
| 8 | +Given a `n * n` matrix `grid` of `0's` and `1's` only. We want to represent the `grid` with a Quad-Tree. |
| 9 | + |
| 10 | +Return _the root of the Quad-Tree_ representing the `grid`. |
| 11 | + |
| 12 | +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. |
| 13 | + |
| 14 | +A Quad-Tree is a tree data structure in which each internal node has exactly four children. Besides, each node has two attributes: |
| 15 | + |
| 16 | +* `val`: True if the node represents a grid of 1's or False if the node represents a grid of 0's. |
| 17 | +* `isLeaf`: True if the node is leaf node on the tree or False if the node has the four children. |
| 18 | +``` |
| 19 | + class Node { |
| 20 | + public boolean val; |
| 21 | + public boolean isLeaf; |
| 22 | + public Node topLeft; |
| 23 | + public Node topRight; |
| 24 | + public Node bottomLeft; |
| 25 | + public Node bottomRight; |
| 26 | + } |
| 27 | +``` |
| 28 | +We can construct a Quad-Tree from a two-dimensional area using the following steps: |
| 29 | + |
| 30 | +1. 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. |
| 31 | +2. 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. |
| 32 | +3. Recurse for each of the children with the proper sub-grid. |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +If you want to know more about the Quad-Tree, you can refer to the [wiki](https://en.wikipedia.org/wiki/Quadtree). |
| 37 | + |
| 38 | +**Quad-Tree format:** |
| 39 | + |
| 40 | +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. |
| 41 | + |
| 42 | +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]`. |
| 43 | + |
| 44 | +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**. |
| 45 | + |
| 46 | +**Example 1:** |
| 47 | + |
| 48 | + |
| 49 | + |
| 50 | +**Input:** grid = \[\[0,1],[1,0]] |
| 51 | + |
| 52 | +**Output:** [[0,1],[1,0],[1,1],[1,1],[1,0]] |
| 53 | + |
| 54 | +**Explanation:** |
| 55 | + |
| 56 | + The explanation of this example is shown below: |
| 57 | + Notice that 0 represnts False and 1 represents True in the photo representing the Quad-Tree. |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | +**Example 2:** |
| 62 | + |
| 63 | + |
| 64 | + |
| 65 | +**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]] |
| 66 | + |
| 67 | +**Output:** [[0,1],[1,1],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]] |
| 68 | + |
| 69 | +**Explanation:** |
| 70 | + |
| 71 | + All values in the grid are not the same. We divide the grid into four sub-grids. |
| 72 | + The topLeft, bottomLeft and bottomRight each has the same value. |
| 73 | + The topRight have different values so we divide it into 4 sub-grids where each has the same value. |
| 74 | + Explanation is shown in the photo below: |
| 75 | + |
| 76 | + |
| 77 | + |
| 78 | +**Constraints:** |
| 79 | + |
| 80 | +* `n == grid.length == grid[i].length` |
| 81 | +* <code>n == 2<sup>x</sup></code> where `0 <= x <= 6` |
| 82 | + |
| 83 | +## Solution |
| 84 | + |
| 85 | +```csharp |
| 86 | +using System.Text; |
| 87 | + |
| 88 | +public class Node { |
| 89 | + public bool val; |
| 90 | + public bool isLeaf; |
| 91 | + public Node? topLeft; |
| 92 | + public Node? topRight; |
| 93 | + public Node? bottomLeft; |
| 94 | + public Node? bottomRight; |
| 95 | + |
| 96 | + public Node(bool val, bool isLeaf) { |
| 97 | + this.val = val; |
| 98 | + this.isLeaf = isLeaf; |
| 99 | + this.topLeft = null; |
| 100 | + this.topRight = null; |
| 101 | + this.bottomLeft = null; |
| 102 | + this.bottomRight = null; |
| 103 | + } |
| 104 | + |
| 105 | + public Node( |
| 106 | + bool val, |
| 107 | + bool isLeaf, |
| 108 | + Node? topLeft, |
| 109 | + Node? topRight, |
| 110 | + Node? bottomLeft, |
| 111 | + Node? bottomRight) { |
| 112 | + this.val = val; |
| 113 | + this.isLeaf = isLeaf; |
| 114 | + this.topLeft = topLeft; |
| 115 | + this.topRight = topRight; |
| 116 | + this.bottomLeft = bottomLeft; |
| 117 | + this.bottomRight = bottomRight; |
| 118 | + } |
| 119 | + |
| 120 | + public override string ToString() { |
| 121 | + StringBuilder sb = new StringBuilder(); |
| 122 | + sb.Append(GetNodeString(this)); |
| 123 | + sb.Append(GetNodeString(topLeft)); |
| 124 | + sb.Append(GetNodeString(topRight)); |
| 125 | + sb.Append(GetNodeString(bottomLeft)); |
| 126 | + sb.Append(GetNodeString(bottomRight)); |
| 127 | + return sb.ToString(); |
| 128 | + } |
| 129 | + |
| 130 | + private string GetNodeString(Node? node) { |
| 131 | + if (node == null) { |
| 132 | + return "[]"; |
| 133 | + } |
| 134 | + return $"[{(node.isLeaf ? "1" : "0")},{(node.val ? "1" : "0")}]"; |
| 135 | + } |
| 136 | +} |
| 137 | + |
| 138 | +/* |
| 139 | +// Definition for a QuadTree node. |
| 140 | +public class Node { |
| 141 | + public bool val; |
| 142 | + public bool isLeaf; |
| 143 | + public Node topLeft; |
| 144 | + public Node topRight; |
| 145 | + public Node bottomLeft; |
| 146 | + public Node bottomRight; |
| 147 | +
|
| 148 | + public Node() { |
| 149 | + val = false; |
| 150 | + isLeaf = false; |
| 151 | + topLeft = null; |
| 152 | + topRight = null; |
| 153 | + bottomLeft = null; |
| 154 | + bottomRight = null; |
| 155 | + } |
| 156 | + |
| 157 | + public Node(bool _val, bool _isLeaf) { |
| 158 | + val = _val; |
| 159 | + isLeaf = _isLeaf; |
| 160 | + topLeft = null; |
| 161 | + topRight = null; |
| 162 | + bottomLeft = null; |
| 163 | + bottomRight = null; |
| 164 | + } |
| 165 | + |
| 166 | + public Node(bool _val,bool _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) { |
| 167 | + val = _val; |
| 168 | + isLeaf = _isLeaf; |
| 169 | + topLeft = _topLeft; |
| 170 | + topRight = _topRight; |
| 171 | + bottomLeft = _bottomLeft; |
| 172 | + bottomRight = _bottomRight; |
| 173 | + } |
| 174 | +} |
| 175 | +*/ |
| 176 | +public class Solution { |
| 177 | + public Node Construct(int[][] grid) { |
| 178 | + return OptimizedDfs(grid, 0, 0, grid.Length); |
| 179 | + } |
| 180 | + |
| 181 | + private Node OptimizedDfs(int[][] grid, int rowStart, int colStart, int len) { |
| 182 | + int zeroCount = 0; |
| 183 | + int oneCount = 0; |
| 184 | + for (int row = rowStart; row < rowStart + len; row++) { |
| 185 | + bool isBreak = false; |
| 186 | + for (int col = colStart; col < colStart + len; col++) { |
| 187 | + if (grid[row][col] == 0) { |
| 188 | + zeroCount++; |
| 189 | + } else { |
| 190 | + oneCount++; |
| 191 | + } |
| 192 | + if (oneCount > 0 && zeroCount > 0) { |
| 193 | + // We really no need to scan all. |
| 194 | + // Once we know there are both 0 and 1 then we can break. |
| 195 | + isBreak = true; |
| 196 | + break; |
| 197 | + } |
| 198 | + } |
| 199 | + if (isBreak) { |
| 200 | + break; |
| 201 | + } |
| 202 | + } |
| 203 | + if (oneCount > 0 && zeroCount > 0) { |
| 204 | + int midLen = len / 2; |
| 205 | + Node topLeft = OptimizedDfs(grid, rowStart, colStart, midLen); |
| 206 | + Node topRight = OptimizedDfs(grid, rowStart, colStart + midLen, midLen); |
| 207 | + Node bottomLeft = OptimizedDfs(grid, rowStart + midLen, colStart, midLen); |
| 208 | + Node bottomRight = OptimizedDfs(grid, rowStart + midLen, colStart + midLen, midLen); |
| 209 | + bool isLeaf = false; |
| 210 | + return new Node(true, isLeaf, topLeft, topRight, bottomLeft, bottomRight); |
| 211 | + } else { |
| 212 | + bool resultVal = oneCount > 0; |
| 213 | + bool isLeaf = true; |
| 214 | + return new Node(resultVal, isLeaf); |
| 215 | + } |
| 216 | + } |
| 217 | +} |
| 218 | +``` |
0 commit comments