519. 随机翻转矩阵
题中给出一个 n_rows 行 n_cols 列的二维矩阵,且所有值被初始化为 0。要求编写一个 flip 函数,均匀随机的将矩阵中的 0 变为 1,并返回该值的位置下标 [row_id,col_id];同样编写一个 reset 函数,将所有的值都重新置为 0。尽量最少调用随机函数 Math.random(),并且优化时间和空间复杂度。
注意:
1 <= n_rows, n_cols <= 10000
0 <= row.id < n_rows 并且 0 <= col.id < n_cols
当矩阵中没有值为 0 时,不可以调用 flip 函数
调用 flip 和 reset 函数的次数加起来不会超过 1000 次
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/random-flip-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
乍一看似乎十分简单,维护一个N*M的矩阵,按照题目要求写就可以了
只需要注意,翻转前判断是不是本身就是1就行了
class Solution {
private int[][] a;
private int n_cols,n_rows;
private ArrayList<ArrayList<Integer>> arrays=new ArrayList<ArrayList<Integer>>();
public Solution(int n_rows, int n_cols) {
a=new int[n_rows][n_cols];
this.n_rows=n_rows;
this.n_cols=n_cols;
}
public int[] flip() {
ArrayList<Integer> arrayList=new ArrayList<Integer>();
arrayList.add((int)(Math.random()*n_rows));
arrayList.add((int)(Math.random()*n_cols));
if(a[arrayList.get(0)][arrayList.get(1)]==1){
return flip();
}
a[arrayList.get(0)][arrayList.get(1)]=1;
arrays.add(arrayList);
return new int[]{arrayList.get(0),arrayList.get(1)};
}
public void reset() {
for(int i=0;i<arrays.size();i++){
a[arrays.get(i).get(0)][arrays.get(i).get(1)]=0;
}
arrays.clear();
}
}
确实,对于最多103 次的操作,一次只影响一个元素来说,存储108 个元素确实是太过分了
这里我们注意到:其实本题并不要求我们整个输出矩阵,而是只需要输出坐标就可以,而且,在上面实现方法中,判断对应位置是否为1,只需要“回想”上一次清零之后是否对该位置进行过翻转即可
class Solution {
private ArrayList<ArrayList> arrayList=new ArrayList<ArrayList>();
int n_cols,n_rows;
public Solution(int n_rows, int n_cols) {
this.n_rows=n_rows;
this.n_cols=n_cols;
}
//翻转点,随机xy并且判断是否已经翻转过了
public int[] flip() {
if(arrayList.size()==n_cols*n_rows){
return null;
}
ArrayList<Integer> array=new ArrayList<Integer>();
array.add((int)(Math.random()*n_rows));
array.add((int)(Math.random()*n_cols));
if(flag(arrayList,array)){
return flip();
}
arrayList.add(array);
return new int[]{array.get(0),array.get(1)};
}
//判断历史记录中是否有这个点
private boolean flag(ArrayList<ArrayList> arrayList,ArrayList array){
for(int i=0;i<arrayList.size();i++){
if(arrayList.get(i).get(0)==array.get(0)&&arrayList.get(i).get(1)==array.get(1)){
return true;
}
}
return false;
}
//清空历史记录即可
public void reset() {
arrayList.clear();
}
}
虽然通过了一次,但是似乎特别不稳定(或者不知道什么原因靠运气通过了一次?)
似乎还是有点麻烦,两层ArrayList操作也麻烦还多用一次Math.random
把二维数组降维打击成一位数组不就方便多了?
class Solution {
private ArrayList<Integer> arrayList=new ArrayList<Integer>();
int n_cols,n_rows;
public Solution(int n_rows, int n_cols) {
this.n_rows=n_rows;
this.n_cols=n_cols;
}
public int[] flip() {
int random=(int)(Math.random()*n_rows*n_cols);
if(flag(arrayList,random)){
return flip();
}
arrayList.add(random);
return new int[]{random/n_cols,random%n_cols};
}
private boolean flag(ArrayList<Integer> arrayList,int random){
for(int i=0;i<arrayList.size();i++){
if(arrayList.get(i)==random){
return true;
}
}
return false;
}
public void reset() {
arrayList.clear();
}
}
这下似乎就可以稳定通过了