描述
给你一个 m x n 的二元矩阵 matrix ,且所有值被初始化为 0 。请你设计一个算法,随机选取一个满足 matrix[i][j] == 0 的下标 (i, j) ,并将它的值变为 1 。所有满足 matrix[i][j] == 0 的下标 (i, j) 被选取的概率应当均等。
尽量最少调用内置的随机函数,并且优化时间和空间复杂度。
分析
不采取措施,直接使用random.nextInt()会导致后面生成的随机数,很大概率是已经被反转过了,做了很多无用功。
解决办法:
使用一维数组表示二维数组,并且把一维数组划分为两半,一半是已经被反转过,一半还没被反转。
用一个map集合给一个已经被反转的位置配对一个未反转的位置。
在没有被反转的一半里生成一个随机数,
- 如果这个随机数的位置x已经被反转了(可以在map中查到),用map找到和他对应的未反转的位置xTo,然后flip()返回的就是xTo,同时跟新与x配对的未完成位置。
- 如果这个随机数的位置x没有被反转,flip()返回的就是x,同时把未反转这一半的最后一个位置做与x配对,写入map。
class Solution {
public int range;
public int m;
public int n;
public Map<Integer,Integer> map;
public Solution(int m, int n) {
this.m = m;
this.n = n;
this.range = m*n;
map = new HashMap<>();
}
public int[] flip() {
int x = new Random().nextInt(range--);
int xTo = map.getOrDefault(x,x);
map.put(x,map.getOrDefault(range,range));
return new int[]{xTo / n, xTo % n};
}
public void reset() {
range = m*n;
map.clear();
}
}