Just to share another perspective and I hope it is interesting.
Suppose that len(nums) = n.
○ for i in 0 ... n - 1: swap(nums[i], nums[random.randint(i, n - 1)]). # uniform sampling in the closed interval [i, n - 1]
○ To generate one sequence, there are n ways of generating the first number, n - 1 ways of generating the second number, n - 2 ways of generating the third number, ..., 1 way of generating the last number. Propability for any particular sequence is (1/n) * (1/(n - 1)) * (1/(n - 2)) * ... * 1/1 = 1/n!.
○ Any generated sequence must be of the same probability 1/n! In fact, we also know that there are n! possible sequences (permutations).
def __init__(self, nums): self.nums = nums def reset(self): return self.nums def shuffle(self): shuffled = self.nums[:] n = len(shuffled) for i in range(n): swapIdx = random.randint(i, n - 1) shuffled[i], shuffled[swapIdx] = shuffled[swapIdx], shuffled[i] return shuffled