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.
Note:
1 <= n_rows, n_cols <= 10000
0 <= row.id < n_rows and 0 <= col.id < n_cols
flip will not be called when the matrix has no 0 values left.
the total number of calls to flip and reset will not exceed 1000.
The input is two lists: the subroutines called and their arguments. Solution’s constructor has two arguments, n_rows and n_cols. flip and reset have no arguments. Arguments are always wrapped with a list, even if there aren’t any.
Constraints etc
minimize calls to random function
optimize the time and space complexity -
Approaches
We can use a reservoir sampling approach.
Mapping a 2D matrix to an array.
Given an index from an array we can compute the row and column of the original matrix as long as we know the number of rows and columns.
/* pick a number between 0 and n_samples - 1 */ vector<int> flip() { int selected; int last = n_samples; // pick random number from 0 to n_samples - 1 int r = rand() % n_samples;
if (indices.find(r) != indices.end()) { // if index already selected before then pick // the next available one from map selected = indices[r]; } else { selected = r; } // store it for when we hit the same index again indices[r] = n_samples; //reduce sample size for next run n_samples--;
/** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(n_rows, n_cols); * vector<int> param_1 = obj.flip(); * obj.reset(); */
Argg 😞
I cannot do
1 2 3 4 5
vector<int> v; // row v[0] = i / n_cols; // column v[1] = i % n_cols;
We should do push_back().
There is also a division by zero problem here.
1 2
// pick random number from 0 to n_samples - 1 int r = rand() % n_samples;
/* pick a number between 0 and n_samples - 1 */ vector<int> flip() { int selected; int last = n_samples; int r = 0; if (n_samples) r = rand() % n_samples;
if (indices.find(r) != indices.end()) { // if index already selected before then pick // the next available one from map selected = indices[r]; } else { selected = r; }
//reduce sample size for next run n_samples--;
// store it for when we hit the same index again, // we want to store it after decrement so we pick the right one indices[r] = n_samples;
int n_samples, n_rows, n_cols; unordered_map<int, int> indices;
public: Solution(int n_rows, int n_cols):n_rows(n_rows), n_cols(n_cols), n_samples(n_rows*n_cols) { srand(time(0)); }
vector<int> flip() { int r = 0; if (n_samples) r = rand() % n_samples;
// if index already selected before then pick // the next available one from map int selected = indices.count(r) ? indices[r] : r;
//reduce sample size for next run n_samples--;
// store it for when we hit the same index again, // we want to store it after decrement so we pick the right one // if the last element indices[r] = indices.count(n_samples) ? indices[n_samples] : n_samples;
int n_samples, n_rows, n_cols; unordered_map<int, int> indices;
public: Solution(int n_rows, int n_cols):n_rows(n_rows), n_cols(n_cols), n_samples(n_rows*n_cols) { srand(time(0)); }
vector<int> flip() { int r = 0; if (n_samples) r = rand() % n_samples;
// if index already selected before then pick // the next available one from map int selected = indices.count(r) ? indices[r] : r;
//reduce sample size for next run n_samples--;
// store it for when we hit the same index again, // we want to store it after decrement so we pick the right one // if the tail element is the map then we pick from map // otherwise we can just store the index indices[r] = indices.count(n_samples) ? indices[n_samples] : n_samples;