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 |
|