一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第29天,点击查看活动详情。
每日刷题 2021.04.29
- leetcode原题链接:leetcode-cn.com/problems/co…
- 难度:简单
- 方法:位运算、自定义排序
题目
-
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.
-
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.
-
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.
示例
- 示例1
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.
- 示例2
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:
提示
n == grid.length == grid[i].length
n == 2x
where0 <= x <= 6
解题思路
- 分析题目:中文的题面看了半小时,都没有看懂后,就切换成英文的题面,看题目。终于看懂了题目。
- 题目的意思:给你一个二维数组,每一个格子都会有一个值,其就是当前的网格值。
- 当整个网格中的所有值都相等,是
0
或者1
的时候,那么isLeaf = true
,val
可以设为网格值,其子项为null
- 当整个网格中存在不想等的值时,
isLeaf = false
,val
为任意值,将整个网格划分成四个,对子网格继续递归,直到网格中的值全部相同为止。
- 当整个网格中的所有值都相等,是
- 那么问题就来了,如何划分呢?
- 根据题意可知,将网格均分为4个,那么可以通过计算当前的网格的横坐标差值 和 纵坐标差值的一半,获得划分后的各个网格的左上角和右下角坐标。
- 通过左上角和右下角的坐标,就可以遍历整个子网格,来判断其所有的网格值是否全部相等。
- 还存在一个问题,如何实现递归呢?(递归三步走)
- 1.返回值和参数
- 2.终止条件
- 3.单层的逻辑
- 返回值:因为要构成一个树,那么我们就需要在每层递归的时候,将根节点返回,这样才能将各个节点嵌套起来。(树中的每一个节点都可以作为一个根节点)
- 参数:因为要确定当前的网格的范围,因此需要网格的左上角和右下角的坐标
- 终止条件:当分到的子网格中的所有网格值全部相等,就可以返回了。也就是找到了叶子节点。找到了叶子节点,就需要创建一个新的
node
节点,将当前的节点信息存储进去,即:isLeaf = true; val = 网格值
,返回给上一层。 - 单层的逻辑:创建一个根节点
root
,递归当前根节点的topLeft、topRight、bottomLeft、bottomRight
三个子节点。
AC
代码
var construct = function(grid) {
let len = grid.length;
if(len == 0) return null;
function dfs(a, b, c, d) {
let temp = grid[a][b], flag = true;
for(let i = a; i <= c && flag; i++) {
for(let j = b; j <= d && flag; j++) {
if(temp != grid[i][j]) {
flag = false;
break;
}
}
}
// flag为真,表示网格值全部为相同的
if(flag){
// 需要进行记录操作
return new Node(temp , true);
}
let root = new Node(temp, false);
// console.log('root:', )
// 表示还需要分割,并不是所有的网格值都相等
// 分割必须是4份
// dx = 7 / 2 = 3
// (0,0) (3,3)
// (0,4) (3,7)
// (4,0) (7,3)
// (4,4) (7,7)
// c = 7 a = 0 7 / 2 = 3
// a = 0, b = 0, c = 7 , d = 7
let dx = c - a + 1, dy = c - a + 1;
root.topLeft = dfs(a, b, a + dx / 2 - 1, b + dy / 2 - 1);
root.topRight = dfs(a, b + dy / 2, a + dx / 2 - 1, d);
root.bottomLeft = dfs(a + dx / 2, b, c, b + dy / 2 - 1);
root.bottomRight = dfs(a + dx / 2, b + dy / 2, c, d);
return root;
}
let no = dfs(0, 0, len - 1, len - 1);
return no;
};
总结
- 下标的问题,下次传入的上一次划定好的区域的下标,不要再将上一层的下标带入。