LeetCode 519 Random Flip Matrix

You are given the number of rows n_rows and number of columns n_cols of a 2D binary matrix where all values are initially 0. Write a function flip which chooses a 0 value uniformly at random, changes it to 1, and then returns the position [row.id, col.id] of that value. Also, write a function reset which sets all values back to 0. Try to minimize the number of calls to system’s Math.random() and optimize the time and space complexity.

class Solution {

    public Solution(int n_rows, int n_cols) {
        
    }
    
    public int[] flip() {
        
    }
    
    public void reset() {
        
    }
}

the description of this question is really easy to understand, let me just rephrase that:
we are gonna implement two method on a matrix full of 0s
1 flip(): we need to randomly flip one position into 1. return this random position
2 reset(): reset everything back to 0s, return nothing.

follow up: try to minimize the number of calls on Math.Random().

idea:
well, for every flip and for every position, we need to check if the value there is 0 or 1, if it is 1, then we need to re-generate a random position…until we hit a 0.
that is not good.
It reminds me of another question:
710 Random Pick with Blacklist
that is one dimension remap, now it should be 2D remap.
自己试着写了写 把自己绕晕了…在remap阶段完全就不知道到底是谁remap到谁。

class Solution {
    int rows;
    int cols;
    int[][] grid;
    HashMap<int[], int[]> map;
    int[] lastOne;

    public Solution(int n_rows, int n_cols) {
        rows = n_rows;
        cols = n_cols;
        grid = new int[rows][cols];
        map = new HashMap<>(); //map contains all the position needs to be remap the can't use to can use
        lastOne = new int[]{0, 0}; //the postion of the first 0 in order
    }
    
    public int[] flip() {
        int x = (int)(Math.random() * rows);
        int y = (int)(Math.random() * cols);
        if (map. containsKey(new int[]{x, y})) { //if they can't be used
            grid[map.get(new int[]{x, y})[0]][map.get(new int[]{x, y})[1]] = 1; //we remap it to some place which can be used
        } else
        //then we remap this one
         //we remap (x, y) to the posistion of lastOne, and then we move last one the next position
        
        
        //we need to update the map each time we finished remapping
        
    }
    
    public void reset() {
        //we need to reset the map tpp
        grid = new int[rows][cols];
        map = new HashMap<>();
    }
}

just look at others’ code, it is so clear.
这个代码的核心也是重定向,每次都往后面填。这个界限的指针就是total。也就是说每一次total-cols*rows都是1.所以我们每一次取随机值从[0, total]里面选择就可以了。

class Solution {
    Map<Integer, Integer> map;
    int rows, cols, total; //total is the number of 0s remained in matrix
    Random rand;

    public Solution(int n_rows, int n_cols) {
        map = new HashMap<>(); //k-the number(index) already used, v-remap this index to a new one
        rand = new Random();
        rows = n_rows;
        cols = n_cols;
        total = rows * cols;
    }
    
    public int[] flip() {
        int r = rand.nextInt(total--);
        int x = map.getOrDefault(r, r); //if r is used, then we return the remap index, or we just use the index of r
        map.put(r, map.getOrDefault(total, total)); //this is like a chain, we gonna find one, this statement actually shows how clear his mind is, and I'm ashamed of myself.
        return new int[]{x / cols, x % cols};
        
    }
    
    public void reset() {
        map.clear();
        total = rows * cols;
    }
}

后续的一点改进:
reset()的时间复杂度仍然为O(N), 这个可以做一些改进,因为clear()的时间复杂度是O(N)
我试着这样:

class Solution {
    Map<Integer, Integer> map;
    int rows, cols, total; //total is the number of 0s remained in matrix
    Random rand;

    public Solution(int n_rows, int n_cols) {
        map = new HashMap<>(); //k-the number(index) already used, v-remap this index to a new one
        rand = new Random();
        rows = n_rows;
        cols = n_cols;
        total = rows * cols;
    }
    
    public int[] flip() {
        int r = rand.nextInt(total--);
        int x = map.getOrDefault(r, r); //if r is used, then we return the remap index, or we just use the index of r
        map.put(r, map.getOrDefault(total, total)); //this is like a chain, we gonna find one, this statement actually shows how clear his mind is, and I'm ashamed of myself.
        return new int[]{x / cols, x % cols};
        
    }
    
    public void reset() {
        map = new HashMap<>();
        total = rows * cols;
    }
}

但是没有什么大的改进。
according to lee215 on leetcode:
请在评论区找到lee215的答案

posted @ 2020-12-08 23:10  EvanMeetTheWorld  阅读(28)  评论(0)    收藏  举报