1. 题目
2. 思路
(1) HashSet
- 利用HashSet存储被选取过的坐标,再次选取时,若选取的下标存在于HashSet中,则重新选取即可。
(2) HashMap
- 将二维数组的下标映射为一维数组,即index=i*n+j,则i=index/n,j=index%n。
- 利用HashMap记录已经选取过的一维坐标。
- 记录已经选取过坐标的数量,每次选取时,从前[m*n-选取过坐标的数量]中随机选取一个坐标,若该坐标之前未被选取过,则将该坐标转换成二维坐标返回,并将该坐标及其映射存入HashMap中,其映射为前[m*n-选取过坐标的数量]中最右端的坐标,因为在本次选取过后,最右端的坐标会被排除,当下一次选取时又选到了该坐标,则根据HashMap的映射,返回当时最右端的坐标。
3. 代码
import java.util.*;
public class Test {
public static void main(String[] args) {
}
}
class Solution {
private Set<Index> set;
private int m;
private int n;
public Solution(int m, int n) {
set = new HashSet<>();
this.m = m;
this.n = n;
}
public int[] flip() {
int x = (int) (Math.random() * m);
int y = (int) (Math.random() * n);
Index res = new Index(x, y);
while (set.contains(res)) {
x = (int) (Math.random() * m);
y = (int) (Math.random() * n);
res = new Index(x, y);
}
set.add(res);
return res.ToArray();
}
public void reset() {
set = new HashSet<>();
}
}
class Index {
private int x;
private int y;
public Index(int x, int y) {
this.x = x;
this.y = y;
}
public int[] ToArray() {
return new int[]{x, y};
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Index)) return false;
Index index = (Index) o;
return x == index.x && y == index.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
class Solution1 {
private int m;
private int n;
private int total;
private Map<Integer, Integer> map;
public Solution1(int m, int n) {
this.m = m;
this.n = n;
total = m * n;
map = new HashMap<>();
}
public int[] flip() {
int index = (int) (Math.random() * total);
total--;
int indexMap = map.getOrDefault(index, index);
map.put(index, map.getOrDefault(total, total));
return new int[]{indexMap / n, indexMap % n};
}
public void reset() {
total = m * n;
map = new HashMap<>();
}
}