跳转至

3391. Design a 3D Binary Matrix with Efficient Layer Tracking 🔒

题目描述

You are given a n x n x n binary 3D array matrix.

Implement the matrix3D class:

  • matrix3D(int n) Initializes the object with the 3D binary array matrix, where all elements are initially set to 0.
  • void setCell(int x, int y, int z) Sets the value at matrix[x][y][z] to 1.
  • void unsetCell(int x, int y, int z) Sets the value at matrix[x][y][z] to 0.
  • int largestMatrix() Returns the index x where matrix[x] contains the most number of 1's. If there are multiple such indices, return the largest x.

 

Example 1:

Input:
["matrix3D", "setCell", "largestMatrix", "setCell", "largestMatrix", "setCell", "largestMatrix"]
[[3], [0, 0, 0], [], [1, 1, 2], [], [0, 0, 1], []]

Output:
[null, null, 0, null, 1, null, 0]

Explanation

matrix3D matrix3D = new matrix3D(3); // Initializes a 3 x 3 x 3 3D array matrix, filled with all 0's.
matrix3D.setCell(0, 0, 0); // Sets matrix[0][0][0] to 1.
matrix3D.largestMatrix(); // Returns 0. matrix[0] has the most number of 1's.
matrix3D.setCell(1, 1, 2); // Sets matrix[1][1][2] to 1.
matrix3D.largestMatrix(); // Returns 1. matrix[0] and matrix[1] tie with the most number of 1's, but index 1 is bigger.
matrix3D.setCell(0, 0, 1); // Sets matrix[0][0][1] to 1.
matrix3D.largestMatrix(); // Returns 0. matrix[0] has the most number of 1's.

Example 2:

Input:
["matrix3D", "setCell", "largestMatrix", "unsetCell", "largestMatrix"]
[[4], [2, 1, 1], [], [2, 1, 1], []]

Output:
[null, null, 2, null, 3]

Explanation

matrix3D matrix3D = new matrix3D(4); // Initializes a 4 x 4 x 4 3D array matrix, filled with all 0's.
matrix3D.setCell(2, 1, 1); // Sets matrix[2][1][1] to 1.
matrix3D.largestMatrix(); // Returns 2. matrix[2] has the most number of 1's.
matrix3D.unsetCell(2, 1, 1); // Sets matrix[2][1][1] to 0.
matrix3D.largestMatrix(); // Returns 3. All indices from 0 to 3 tie with the same number of 1's, but index 3 is the biggest.

 

Constraints:

  • 1 <= n <= 100
  • 0 <= x, y, z < n
  • At most 105 calls are made in total to setCell and unsetCell.
  • At most 104 calls are made to 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$。

时间复杂度方面,setCellunsetCell 方法的时间复杂度均为 $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
34
35
36
from sortedcontainers import SortedList


class matrix3D:

    def __init__(self, n: int):
        self.g = [[[0] * n for _ in range(n)] for _ in range(n)]
        self.cnt = [0] * n
        self.sl = SortedList(key=lambda x: (-x[0], -x[1]))

    def setCell(self, x: int, y: int, z: int) -> None:
        if self.g[x][y][z]:
            return
        self.g[x][y][z] = 1
        self.sl.discard((self.cnt[x], x))
        self.cnt[x] += 1
        self.sl.add((self.cnt[x], x))

    def unsetCell(self, x: int, y: int, z: int) -> None:
        if self.g[x][y][z] == 0:
            return
        self.g[x][y][z] = 0
        self.sl.discard((self.cnt[x], x))
        self.cnt[x] -= 1
        if self.cnt[x]:
            self.sl.add((self.cnt[x], x))

    def largestMatrix(self) -> int:
        return self.sl[0][1] if self.sl else len(self.g) - 1


# Your matrix3D object will be instantiated and called as such:
# obj = matrix3D(n)
# obj.setCell(x,y,z)
# obj.unsetCell(x,y,z)
# param_3 = obj.largestMatrix()
 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
class matrix3D {
    private final int[][][] g;
    private final int[] cnt;
    private final TreeSet<int[]> sl
        = new TreeSet<>((a, b) -> a[0] == b[0] ? b[1] - a[1] : b[0] - a[0]);

    public matrix3D(int n) {
        g = new int[n][n][n];
        cnt = new int[n];
    }

    public void setCell(int x, int y, int z) {
        if (g[x][y][z] == 1) {
            return;
        }
        g[x][y][z] = 1;
        sl.remove(new int[] {cnt[x], x});
        cnt[x]++;
        sl.add(new int[] {cnt[x], x});
    }

    public void unsetCell(int x, int y, int z) {
        if (g[x][y][z] == 0) {
            return;
        }
        g[x][y][z] = 0;
        sl.remove(new int[] {cnt[x], x});
        cnt[x]--;
        if (cnt[x] > 0) {
            sl.add(new int[] {cnt[x], x});
        }
    }

    public int largestMatrix() {
        return sl.isEmpty() ? g.length - 1 : sl.first()[1];
    }
}

/**
 * Your matrix3D object will be instantiated and called as such:
 * matrix3D obj = new matrix3D(n);
 * obj.setCell(x,y,z);
 * obj.unsetCell(x,y,z);
 * int param_3 = obj.largestMatrix();
 */
 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
class matrix3D {
private:
    vector<vector<vector<int>>> g;
    vector<int> cnt;
    set<pair<int, int>> sl;

public:
    matrix3D(int n) {
        g.resize(n, vector<vector<int>>(n, vector<int>(n, 0)));
        cnt.resize(n, 0);
    }

    void setCell(int x, int y, int z) {
        if (g[x][y][z] == 1) {
            return;
        }
        g[x][y][z] = 1;
        sl.erase({-cnt[x], -x});
        cnt[x]++;
        sl.insert({-cnt[x], -x});
    }

    void unsetCell(int x, int y, int z) {
        if (g[x][y][z] == 0) {
            return;
        }
        g[x][y][z] = 0;
        sl.erase({-cnt[x], -x});
        cnt[x]--;
        if (cnt[x]) {
            sl.insert({-cnt[x], -x});
        }
    }

    int largestMatrix() {
        return sl.empty() ? g.size() - 1 : -sl.begin()->second;
    }
};

/**
 * Your matrix3D object will be instantiated and called as such:
 * matrix3D* obj = new matrix3D(n);
 * obj->setCell(x,y,z);
 * obj->unsetCell(x,y,z);
 * int param_3 = obj->largestMatrix();
 */
1

评论