lc 519. random flip matrix

Description

1
2
3
4
5
6
7
8
You are given the number of rows n_rows and number of columns n_cols of a 2D binary matrix where all values are initially 0. Write a function flip which chooses a 0 value uniformly at random, changes it to 1, and then returns the position [row.id, col.id] of that value. Also, write a function reset which sets all values back to 0. Try to minimize the number of calls to system's Math.random() and optimize the time and space complexity.

Note:

1 <= n_rows, n_cols <= 10000
0 <= row.id < n_rows and 0 <= col.id < n_cols
flip will not be called when the matrix has no 0 values left.
the total number of calls to flip and reset will not exceed 1000.
1
2
3
4
5
6
Example 1:

Input:
["Solution","flip","flip","flip","flip"]
[[2,3],[],[],[],[]]
Output: [null,[0,1],[1,2],[1,0],[1,1]]

Solution

1
2
3
4
It is like a shuffle problem.
First, any cell can be converted to a number in [0, n_rows * n_cols), so we only need to generate the random number in that range without repetition.
Second, recall the random shuffle algo, every time, we generate a number i in [0, total) and exchange the number at index i and total - 1, then total -= 1.
However, if we use array to implement it, it will be MLE. So we can use map, the only difference is that if i is not in that map, we should return i. (self.d.get(i, i))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class :

def __init__(self, n_rows: int, n_cols: int):
self.total = n_rows * n_cols
self.d = {}
self.r, self.c = n_rows, n_cols

def flip(self) -> List[int]:
i = random.randint(0, self.total - 1)
self.total -= 1
res = self.d.get(i, i)

self.d[i], self.d[self.total] = self.d.get(self.total, self.total), res
return (res // self.c, res % self.c)


def reset(self) -> None:
self.total = self.r * self.c