100% 1 random() only per flip() call | with explanation
Intuition\nAn used_element hashset + while loop solution may calls random()more than 1 time per flip() which againsts the requirement.\nA pre-shuffled array on 
# Intuition\nAn `used_element` hashset + while loop solution may calls `random()`more than 1 time per `flip()` which againsts the requirement.\nA pre-shuffled array on `init()` exceeds memory limit.\n<!-- Describe your first thoughts on how to solve this problem. -->\n\n# Approach\n1. Flattern an `m x n` met into a linear array with `length=m*n`.\n2. Use a variable `last_idx=len(arr) - 1` to indicate the index of the last element.\n3. On every `flip()`, we choose a random index from `0` to `last_idx` and the `v = arr[idx]` is our random value.\n4. Since we flipped `arr[idx]` already, we now move `arr[last_idx]` to `arr[idx]` and reduce `last_idx -= 1`.\n5. Return `v // n, v % n` as `i, j`.\n6. This algorithm works but it exceeds the memory limit. Since the values in the array are the same as their indices unless they are changed, we don\'t really need a linear array to store it, we use a hashmap with `default_value=key` instead.\n<!-- Describe your approach to solving the problem. -->\n\n# Complexity\n- Time complexity:\n<!-- Add your time complexity here, e.g. $$O(n)$$ -->\n\n- Space complexity:\n<!-- Add your space complexity here, e.g. $$O(n)$$ -->\n\n# Code\n```\nclass Solution:\n    def __init__(self, m: int, n: int):\n        self.n, self.len = n, m * n\n        self.items = {}\n        self.last_idx = self.len-1\n\n    def flip(self) -> List[int]:\n        idx = random.randint(0, self.last_idx)\n        v = self.items.get(idx, idx)\n        self.items[idx] = self.items.get(self.last_idx, self.last_idx)\n        self.last_idx -= 1\n        return divmod(v, self.n)\n\n    def reset(self) -> None:\n        self.items.clear()\n        self.last_idx = self.len-1\n\n```
['Python3']