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的答案

浙公网安备 33010602011771号