519. 随机翻转矩阵 (hash 映射移动到最后)
难度中等
给你一个 m x n
的二元矩阵 matrix
,且所有值被初始化为 0
。请你设计一个算法,随机选取一个满足 matrix[i][j] == 0
的下标 (i, j)
,并将它的值变为 1
。所有满足 matrix[i][j] == 0
的下标 (i, j)
被选取的概率应当均等。
尽量最少调用内置的随机函数,并且优化时间和空间复杂度。
实现 Solution
类:
Solution(int m, int n)
使用二元矩阵的大小m
和n
初始化该对象int[] flip()
返回一个满足matrix[i][j] == 0
的随机下标[i, j]
,并将其对应格子中的值变为1
void reset()
将矩阵中所有的值重置为0
示例:
输入 ["Solution", "flip", "flip", "flip", "reset", "flip"] [[3, 1], [], [], [], [], []] 输出 [null, [1, 0], [2, 0], [0, 0], null, [2, 0]] 解释 Solution solution = new Solution(3, 1); solution.flip(); // 返回 [1, 0],此时返回 [0,0]、[1,0] 和 [2,0] 的概率应当相同 solution.flip(); // 返回 [2, 0],因为 [1,0] 已经返回过了,此时返回 [2,0] 和 [0,0] 的概率应当相同 solution.flip(); // 返回 [0, 0],根据前面已经返回过的下标,此时只能返回 [0,0] solution.reset(); // 所有值都重置为 0 ,并可以再次选择下标返回 solution.flip(); // 返回 [2, 0],此时返回 [0,0]、[1,0] 和 [2,0] 的概率应当相同
提示:
1 <= m, n <= 104
- 每次调用
flip
时,矩阵中至少存在一个值为 0 的格子。 - 最多调用
1000
次flip
和reset
方法。
1 class Solution { 2 public: 3 int last_index; 4 int m; 5 int n; 6 unordered_map<int,int> aa_map; 7 Solution(int m, int n) { 8 //index=a*n+b; 9 this->last_index = m*n; 10 this->m = m; 11 this->n = n; 12 } 13 14 vector<int> flip() { 15 int tt = rand()% last_index; 16 last_index--; 17 // 先计算结果 18 int res = tt; 19 if (aa_map.count(tt)) { 20 res = aa_map[tt]; 21 } 22 // 反转覆盖 23 if (aa_map.count(last_index)) { 24 aa_map[tt] = aa_map[last_index]; 25 } else { 26 aa_map[tt] = last_index; 27 } 28 int res1 = res/n; 29 int res2 = res%n; 30 return vector<int>({res1,res2}); 31 } 32 33 void reset() { 34 aa_map.clear(); 35 last_index = m*n; 36 } 37 }; 38 39 /** 40 * Your Solution object will be instantiated and called as such: 41 * Solution* obj = new Solution(m, n); 42 * vector<int> param_1 = obj->flip(); 43 * obj->reset(); 44 */