LeetCode 519. 随机翻转矩阵

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();
    }
}


这下似乎就可以稳定通过了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值