3391. 设计一个高效的层跟踪三维二进制矩阵 🔒
题目描述
给定一个 n x n x n
的 二进制 三维数组 matrix
。
实现 Matrix3D
类:
Matrix3D(int n)
用三维二进制数组matrix
初始化对象,其中 所有 元素都初始化为 0。void setCell(int x, int y, int z)
将matrix[x][y][z]
的值设为 1。void unsetCell(int x, int y, int z)
将matrix[x][y][z]
的值设为 0。int largestMatrix()
返回包含最多 1 的matrix[x]
的下标x
。如果这样的对应值有多个,返回 最大的x
。
示例 1:
输入:
["Matrix3D", "setCell", "largestMatrix", "setCell", "largestMatrix", "setCell", "largestMatrix"]
[[3], [0, 0, 0], [], [1, 1, 2], [], [0, 0, 1], []]
输出:
[null, null, 0, null, 1, null, 0]
解释:
Matrix3D matrix3D = new Matrix3D(3); // 初始化一个3 x 3 x 3
的三维数组 matrix
,用全 0 填充。matrix3D.setCell(0, 0, 0); // 将
matrix[0][0][0]
设为 1。matrix3D.largestMatrix(); // 返回 0。
matrix[0]
1 的数量最多。matrix3D.setCell(1, 1, 2); // 将
matrix[1][1][2]
设为 1。matrix3D.largestMatrix(); // 返回 1。
matrix[0]
和 matrix[1]
1 的数量一样多,但下标 1 更大。matrix3D.setCell(0, 0, 1); // 将
matrix[0][0][1]
设为 1。matrix3D.largestMatrix(); // 返回 0。
matrix[0]
1 的数量最多。示例 2:
输入:
["Matrix3D", "setCell", "largestMatrix", "unsetCell", "largestMatrix"]
[[4], [2, 1, 1], [], [2, 1, 1], []]
输出:
[null, null, 2, null, 3]
解释:
Matrix3D matrix3D = new matrix3D(4); // 初始化一个4 x 4 x 4
的三维数组 matrix
,用全 0 填充。matrix3D.setCell(2, 1, 1); // 将
matrix[2][1][1]
设为 1。matrix3D.largestMatrix(); // 返回 2。
matrix[2]
1 的数量最多。matrix3D.unsetCell(2, 1, 1); // 将
matrix[2][1][1]
设为 0。matrix3D.largestMatrix(); // 返回 3。0 到 3 的对应值都有相同数量的 1,但下标 3 最大。
提示:
1 <= n <= 100
0 <= x, y, z < n
- 最多总共调用
105
次setCell
和unsetCell
。 - 最多调用
104
次largestMatrix
。
解法
方法一:计数 + 有序集合
我们使用一个三维数组 $\textit{g}$ 来表示矩阵,其中 $\textit{g}[x][y][z]$ 表示矩阵中坐标 $(x, y, z)$ 的值,用一个长度为 $n$ 的数组 $\textit{cnt}$ 来记录每一层的 $1$ 的个数,用一个有序集合 $\textit{sl}$ 来维护每一层的 $1$ 的个数和层数,其中 $\textit{sl}$ 中的元素是 $(\textit{cnt}[x], x)$,这样 $\textit{sl}$ 就能按照 $1$ 的个数降序排序,如果 $1$ 的个数相同,则按照层数降序排序。
调用 setCell
方法时,我们先判断 $(x, y, z)$ 是否已经被设置为 $1$,如果是则直接返回,否则将 $\textit{g}[x][y][z]$ 设置为 $1$,然后将 $(\textit{cnt}[x], x)$ 从 $\textit{sl}$ 中删除,将 $\textit{cnt}[x]$ 加一,再将 $(\textit{cnt}[x], x)$ 加入 $\textit{sl}$。
调用 unsetCell
方法时,我们先判断 $(x, y, z)$ 是否已经被设置为 $0$,如果是则直接返回,否则将 $\textit{g}[x][y][z]$ 设置为 $0$,然后将 $(\textit{cnt}[x], x)$ 从 $\textit{sl}$ 中删除,将 $\textit{cnt}[x]$ 减一,如果 $\textit{cnt}[x]$ 大于 $0$,则将 $(\textit{cnt}[x], x)$ 加入 $\textit{sl}$。
调用 largestMatrix
方法时,我们返回 $\textit{sl}$ 中第一个元素的第二个值,如果 $\textit{sl}$ 为空,则返回 $n - 1$。
时间复杂度方面,setCell
和 unsetCell
方法的时间复杂度均为 $O(\log n)$,largestMatrix
方法的时间复杂度为 $O(1)$。空间复杂度 $O(n^3)$。
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 |
|
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 34 35 36 37 38 39 40 41 42 43 44 45 |
|
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 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|
1 |
|