Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
There is an m x n binary grid matrix with all the values set 0 initially. Design an algorithm to randomly pick an index (i, j) where matrix[i][j] == 0 and flips it to 1. All the indices (i, j) where matrix[i][j] == 0 should be equally likely to be returned.
Optimize your algorithm to minimize the number of calls made to the built-in random function of your language and optimize the time and space complexity.
Implement the Solution class:
Solution(int m, int n) Initializes the object with the size of the binary matrix m and n.int[] flip() Returns a random index [i, j] of the matrix where matrix[i][j] == 0 and flips it to 1.void reset() Resets all the values of the matrix to be 0.Example 1:
Input ["Solution", "flip", "flip", "flip", "reset", "flip"] [[3, 1], [], [], [], [], []] Output [null, [1, 0], [2, 0], [0, 0], null, [2, 0]] Explanation Solution solution = new Solution(3, 1); solution.flip(); // return [1, 0], [0,0], [1,0], and [2,0] should be equally likely to be returned. solution.flip(); // return [2, 0], Since [1,0] was returned, [2,0] and [0,0] solution.flip(); // return [0, 0], Based on the previously returned indices, only [0,0] can be returned. solution.reset(); // All the values are reset to 0 and can be returned. solution.flip(); // return [2, 0], [0,0], [1,0], and [2,0] should be equally likely to be returned.
Constraints:
1 <= m, n <= 104flip.1000 calls will be made to flip and reset.Problem summary: There is an m x n binary grid matrix with all the values set 0 initially. Design an algorithm to randomly pick an index (i, j) where matrix[i][j] == 0 and flips it to 1. All the indices (i, j) where matrix[i][j] == 0 should be equally likely to be returned. Optimize your algorithm to minimize the number of calls made to the built-in random function of your language and optimize the time and space complexity. Implement the Solution class: Solution(int m, int n) Initializes the object with the size of the binary matrix m and n. int[] flip() Returns a random index [i, j] of the matrix where matrix[i][j] == 0 and flips it to 1. void reset() Resets all the values of the matrix to be 0.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Math
["Solution","flip","flip","flip","reset","flip"] [[3,1],[],[],[],[],[]]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #519: Random Flip Matrix
class Solution {
private int m;
private int n;
private int total;
private Random rand = new Random();
private Map<Integer, Integer> mp = new HashMap<>();
public Solution(int m, int n) {
this.m = m;
this.n = n;
this.total = m * n;
}
public int[] flip() {
int x = rand.nextInt(total--);
int idx = mp.getOrDefault(x, x);
mp.put(x, mp.getOrDefault(total, total));
return new int[] {idx / n, idx % n};
}
public void reset() {
total = m * n;
mp.clear();
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(m, n);
* int[] param_1 = obj.flip();
* obj.reset();
*/
// Accepted solution for LeetCode #519: Random Flip Matrix
// Auto-generated Go example from java.
func exampleSolution() {
}
// Reference (java):
// // Accepted solution for LeetCode #519: Random Flip Matrix
// class Solution {
// private int m;
// private int n;
// private int total;
// private Random rand = new Random();
// private Map<Integer, Integer> mp = new HashMap<>();
//
// public Solution(int m, int n) {
// this.m = m;
// this.n = n;
// this.total = m * n;
// }
//
// public int[] flip() {
// int x = rand.nextInt(total--);
// int idx = mp.getOrDefault(x, x);
// mp.put(x, mp.getOrDefault(total, total));
// return new int[] {idx / n, idx % n};
// }
//
// public void reset() {
// total = m * n;
// mp.clear();
// }
// }
//
// /**
// * Your Solution object will be instantiated and called as such:
// * Solution obj = new Solution(m, n);
// * int[] param_1 = obj.flip();
// * obj.reset();
// */
# Accepted solution for LeetCode #519: Random Flip Matrix
class Solution:
def __init__(self, m: int, n: int):
self.m = m
self.n = n
self.total = m * n
self.mp = {}
def flip(self) -> List[int]:
self.total -= 1
x = random.randint(0, self.total)
idx = self.mp.get(x, x)
self.mp[x] = self.mp.get(self.total, self.total)
return [idx // self.n, idx % self.n]
def reset(self) -> None:
self.total = self.m * self.n
self.mp.clear()
# Your Solution object will be instantiated and called as such:
# obj = Solution(m, n)
# param_1 = obj.flip()
# obj.reset()
// Accepted solution for LeetCode #519: Random Flip Matrix
use rand::prelude::*;
use std::collections::HashMap;
struct Solution {
size: usize,
indexes: HashMap<usize, usize>,
rng: ThreadRng,
rows: usize,
cols: usize,
}
impl Solution {
fn new(n_rows: i32, n_cols: i32) -> Self {
let rows = n_rows as usize;
let cols = n_cols as usize;
let size = rows * cols;
let indexes = HashMap::new();
let rng = thread_rng();
Solution {
size,
indexes,
rng,
rows,
cols,
}
}
fn flip(&mut self) -> Vec<i32> {
let r = self.rng.gen_range(0, self.size);
let x = *self.indexes.entry(r).or_insert(r);
self.size -= 1;
let y = *self.indexes.entry(self.size).or_insert(self.size);
*self.indexes.entry(r).or_default() = y;
let col = x % self.cols;
let row = x / self.cols;
vec![row as i32, col as i32]
}
fn reset(&mut self) {
self.size = self.rows * self.cols;
self.indexes = HashMap::new();
}
}
// Accepted solution for LeetCode #519: Random Flip Matrix
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #519: Random Flip Matrix
// class Solution {
// private int m;
// private int n;
// private int total;
// private Random rand = new Random();
// private Map<Integer, Integer> mp = new HashMap<>();
//
// public Solution(int m, int n) {
// this.m = m;
// this.n = n;
// this.total = m * n;
// }
//
// public int[] flip() {
// int x = rand.nextInt(total--);
// int idx = mp.getOrDefault(x, x);
// mp.put(x, mp.getOrDefault(total, total));
// return new int[] {idx / n, idx % n};
// }
//
// public void reset() {
// total = m * n;
// mp.clear();
// }
// }
//
// /**
// * Your Solution object will be instantiated and called as such:
// * Solution obj = new Solution(m, n);
// * int[] param_1 = obj.flip();
// * obj.reset();
// */
Use this to step through a reusable interview workflow for this problem.
For each element, scan the rest of the array looking for a match. Two nested loops give n × (n−1)/2 comparisons = O(n²). No extra space since we only use loop indices.
One pass through the input, performing O(1) hash map lookups and insertions at each step. The hash map may store up to n entries in the worst case. This is the classic space-for-time tradeoff: O(n) extra memory eliminates an inner loop.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.