LC 558. 四叉树交集
题目描述
这是 LeetCode 上的 558. 四叉树交集 ,难度为 中等。
二进制矩阵中的所有元素不是 $0$ 就是 $1$ 。
给你两个四叉树,quadTree1
和 quadTree2
。
其中 quadTree1
表示一个 $n \times n$ 二进制矩阵,而 quadTree2
表示另一个 $n \times n$ 二进制矩阵。
请你返回一个表示 $n \times n$ 二进制矩阵的四叉树,它是 quadTree1
和 quadTree2
所表示的两个二进制矩阵进行 按位逻辑或运算 的结果。
注意,当 isLeaf
为 False
时,你可以把 True
或者 False
赋值给节点,两种值都会被判题机制接受。
四叉树数据结构中,每个内部节点只有四个子节点。
此外,每个节点都有两个属性:
val
:储存叶子结点所代表的区域的值。$1$ 对应True
,$0$ 对应False
;isLeaf
: 当这个节点是一个叶子结点时为True
,如果它有 $4$ 个子节点则为False
。
1 |
|
我们可以按以下步骤为二维区域构建四叉树:
- 如果当前网格的值相同(即全为 $0$ 或者全为 $1$),将
isLeaf
设为True
,将val
设为网格相应的值,并将四个子节点都设为Null
然后停止。 - 如果当前网格的值不同,将
isLeaf
设为False
, 将val
设为任意值,然后如下图所示,将当前网格划分为四个子网格。 - 使用适当的子网格递归每个子节点。
四叉树格式:
输出为使用层序遍历后四叉树的序列化形式,其中 null 表示路径终止符,其下面不存在节点。
它与二叉树的序列化非常相似。唯一的区别是节点以列表形式表示 [isLeaf, val]
。
如果 isLeaf
或者 val
的值为 True
,则表示它在列表 [isLeaf, val]
中的值为 $1$ ;如果 isLeaf
或者 val
的值为 False
,则表示值为 $0$ 。
示例 1:
1 |
|
示例 2:1
2
3
4
5
6
7输入:quadTree1 = [[1,0]]
, quadTree2 = [[1,0]]
输出:[[1,0]]
解释:两个数所表示的矩阵大小都为 1*1,值全为 0
结果矩阵大小为 1*1,值全为 0 。
示例 3:1
2
3
4输入:quadTree1 = [[0,0],[1,0],[1,0],[1,1],[1,1]]
, quadTree2 = [[0,0],[1,1],[1,1],[1,0],[1,1]]
输出:[[1,1]]
示例 4:1
2
3
4输入:quadTree1 = [[0,0],[1,1],[1,0],[1,1],[1,1]]
, quadTree2 = [[0,0],[1,1],[0,1],[1,1],[1,1],null,null,null,null,[1,1],[1,0],[1,0],[1,1]]
输出:[[0,0],[1,1],[0,1],[1,1],[1,1],null,null,null,null,[1,1],[1,0],[1,0],[1,1]]
示例 5:1
2
3
4输入:quadTree1 = [[0,1],[1,0],[0,1],[1,1],[1,0],null,null,null,null,[1,0],[1,0],[1,1],[1,1]]
, quadTree2 = [[0,1],[0,1],[1,0],[1,1],[1,0],[1,0],[1,0],[1,1],[1,1]]
输出:[[0,0],[0,1],[0,1],[1,1],[1,0],[1,0],[1,0],[1,1],[1,1],[1,0],[1,0],[1,1],[1,1]]
提示:
quadTree1
和quadTree2
都是符合题目要求的四叉树,每个都代表一个 $n \times n$ 的矩阵。- $n = 2^x$ ,其中 $0 <= x <= 9$
递归
为了方便,我们令 quadTree1
为 t1
,令 quadTree2
为 t2
。
根据题意,并利用给定函数作为递归函数,当 t1
和 t2
均为叶子节点时,根据 t1
和 t2
的值情况分别处理,若 t1
和 t2
中存在值为 $1$ 的节点,返回该节点,否则(两者均为 $0$),返回任一节点。
然后考虑其他情况下,如何使用 t1
和 t2
构造新节点 ans
,分别使用对应位置的进行「递归」构造即可(即使用 t1.topLeft
和 t2.topLeft
来赋值给 ans.topLeft
,其余位置同理),要注意可能存在 t1
或 t2
其中一节点为叶子节点的情况,此时应当使用当前叶子节点和另一节点的子节点进行构造。
最后考虑什么情况下,会产生新的叶子节点:若当前节点 ans
的四个子节点均为叶子节点,并且值相同时,ans
会成为叶子节点,ans
值为叶子节点的值,此时需要执行的操作为将 isLeaf
设定为 True
,修改 val
为原子节点的值,将四个原子节点置空。
Java 代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class Solution {
public Node intersect(Node t1, Node t2) {
if (t1.isLeaf && t2.isLeaf) {
if (t1.val) return t1;
else if (t2.val) return t2;
else return t1;
}
Node ans = new Node();
ans.topLeft = intersect(t1.isLeaf ? t1 : t1.topLeft, t2.isLeaf ? t2 : t2.topLeft);
ans.topRight = intersect(t1.isLeaf ? t1 : t1.topRight, t2.isLeaf ? t2 : t2.topRight);
ans.bottomLeft = intersect(t1.isLeaf ? t1 : t1.bottomLeft, t2.isLeaf ? t2 : t2.bottomLeft);
ans.bottomRight = intersect(t1.isLeaf ? t1 : t1.bottomRight, t2.isLeaf ? t2 : t2.bottomRight);
boolean a = ans.topLeft.isLeaf && ans.topRight.isLeaf && ans.bottomLeft.isLeaf && ans.bottomRight.isLeaf;
boolean b = ans.topLeft.val && ans.topRight.val && ans.bottomLeft.val && ans.bottomRight.val;
boolean c = ans.topLeft.val || ans.topRight.val || ans.bottomLeft.val || ans.bottomRight.val;
ans.isLeaf = a && (b || !c);
ans.val = ans.topLeft.val;
if (ans.isLeaf) ans.topLeft = ans.topRight = ans.bottomLeft = ans.bottomRight = null;
return ans;
}
}
TypeScript 代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19function intersect(t1: Node | null, t2: Node | null): Node | null {
if (t1.isLeaf && t2.isLeaf) {
if (t1.val) return t1
else if (t2.val) return t2
else return t1
}
const ans: Node = new Node()
ans.topLeft = intersect(t1.isLeaf ? t1 : t1.topLeft, t2.isLeaf ? t2 : t2.topLeft)
ans.topRight = intersect(t1.isLeaf ? t1 : t1.topRight, t2.isLeaf ? t2 : t2.topRight)
ans.bottomLeft = intersect(t1.isLeaf ? t1 : t1.bottomLeft, t2.isLeaf ? t2 : t2.bottomLeft)
ans.bottomRight = intersect(t1.isLeaf ? t1 : t1.bottomRight, t2.isLeaf ? t2 : t2.bottomRight)
const a: boolean = ans.topLeft.isLeaf && ans.topRight.isLeaf && ans.bottomLeft.isLeaf && ans.bottomRight.isLeaf
const b: boolean = ans.topLeft.val && ans.topRight.val && ans.bottomLeft.val && ans.bottomRight.val
const c: boolean = ans.topLeft.val || ans.topRight.val || ans.bottomLeft.val || ans.bottomRight.val
ans.isLeaf = a && (b || !c)
ans.val = ans.topLeft.val
if (ans.isLeaf) ans.topLeft = ans.topRight = ans.bottomLeft = ans.bottomRight = null
return ans
};
- 时间复杂度:复杂度与最终矩阵大小相关,而最终矩阵大小不会超过原矩阵大小,复杂度为 $O(n^2)$
- 空间复杂度:忽略递归带来的额外空间开销,复杂度为 $O(1)$
加餐
另外一道也是「四叉树」相关的递归运用题 : 【综合笔试题】难度 2/5,递归运用及前缀和优化 🎉🎉
最后
这是我们「刷穿 LeetCode」系列文章的第 No.558
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!