Well Explained Python with example; call random once every time
nspired by @akaenki and Durstenfeld version Fisher\u2013Yates shuffle\nThe baisc idea: flatten matrix to 1-d array; each time we filp a element, swap it with en
nspired by @[akaenki](http://https://leetcode.com/problems/random-flip-matrix/discuss/154053/Java-AC-Solution-call-Least-times-of-Random.nextInt()-function) and D[urstenfeld version Fisher\u2013Yates shuffle](http://https://en.wikipedia.org/wiki/Fisher\u2013Yates_shuffle#Examples)\nThe baisc idea: flatten matrix to 1-d array; each time we filp a element, swap it with end of current array tail, and decrease the array size by 1; Therefore, we won\'t touch fliped elements and keep the flip uniformly\nNote: elements in the valid range of index array are untouched indexes; and each element is not related to indexes of index array\n\n\n```\nexample: [[0, 0], [0, 0]]\nstep 1: flatten it to 1-d index array [0, 1, 2, 3|]; remain = 4\nstep 2: remain = 3; get a random index, say index = 0; 0 did not swap with other index; update swap[0] = 3 (current tail);\n\t\tindex array [3, 1, 2,| 0] (index before | means untouched, afterwards means flipped); return [0 // 2, 0 % 2]\n\t\tthe original matrix will be [[1, 0], [0, 0]]\nstep 3: remain = 2; get a random index, say index = 0 as before; 0 swapped with 3, thus actual index = 3; update swap[0] = 2 (current tail), which means swap elemnets of index 0 with element of index 2\n\t\tindex array [2, 1,| 3, 0] (index before | means untouched, afterwards means flipped); return [3 // 2, 3 % 2]\n\t\tthe original matrix will be [[1, 0], [0, 1]]\nstep 4: remain = 1; get a random index, say index = 0 as before; 0 swapped with 2, thus actual index = 2; update swap[0] = 1 (current tail), which means swap elemnets of index 0 with element of index 1\n\t\tindex array [1,| 2, 3, 0] (index before | means untouched, afterwards means flipped); return [2 // 2, 2 % 2]\n\t\tthe original matrix will be [[1, 0], [1, 1]]\nstep 5: remain = 0; get a random index, say index = 0 as before; 0 swapped with 1, thus actual index = 1; update swap[0] = 0 (current tail), which means swap elemnets of index 0 with element of index 0\n\t\tindex array [|1, 2, 3, 0] (index before | means untouched, afterwards means flipped); return [1 // 2, 1 % 2]\n\t\tthe original matrix will be [[1, 1], [1, 1]]\n```\n\n```\nimport random\nclass Solution:\n\n    def __init__(self, n_rows: int, n_cols: int):\n        self.rows, self.cols = n_rows, n_cols\n        self.remain = self.rows*self.cols  # the number of remaining 0\n        self.swap = {}  # {original index : new index}\n\n    def flip(self) -> List[int]:\n\t\t# after flipping, there must be a 0 to be changed to 1\n        self.remain -= 1\n        index = random.randint(0, self.remain)  # return a random index from [0, self.remain], valid range\n        actualIndex = index  # actual index based on matrix\n        # if there is a swap operation happened at this index, find the exact index element on this index now\n\t    if index in self.swap:\n            actualIndex = self.swap[index]\n        tail = self.remain\n\t\t# if there is a swap operation happened at this tail index, find the exact index element on this tail index now\n        if tail in self.swap: \n            tail = self.swap[tail]\n        self.swap[index] = tail  # swap this index with actual tail index\n        return [actualIndex // self.cols, actualIndex % self.cols]\n        \n    def reset(self) -> None:\n        self.swap = {}\n        self.remain = self.rows*self.cols\n```\n
[]