leetcode 384
class Solution:
def __init__(self, nums: List[int]):
self.nums = nums
self.ori = nums[:]
self.n = len(nums)
def reset(self) -> List[int]:
self.nums = self.ori[:]
return self.nums
def shuffle(self) -> List[int]:
# 1st: 在[0, n-1]随机选一个与 [0] 位置交换,每个数被换到[0]的概率是 1/n
# 2nd: 在[1, n-1]随机选一个与 [1] 位置交换,
# 每个数被换到[1]的概率是 (n-1)/n * 1/(n-1) # 第一轮没被选择的概率 * 第二轮被选中的概率
for i in range(self.n):
rand_idx = random.randint(i, self.n - 1)
self.nums[rand_idx], self.nums[i] = self.nums[i], self.nums[rand_idx]
return self.nums
第一轮,在[0,n-1] 上随机选一个与0位置交换,每个数的概率是 1/n
第二轮, 在[1,n-1] 上随机选一个与1位置交换,每个数的概率是 (n-1)/n * 1/(n-1) = 1/n # 第一轮没被选择的概率 * 第二轮被选中的概率
第三轮, 在[2,n-1] 上随机选一个与2位置交换,每个数的概率是 (n-1)/n * (n-2)/(n-1) * 1/(n-2) = 1/n # 第一轮没被选择的概率 * 第二轮没被选中的概率 * 第三轮被选中的概率
。。。以此类推
leetcode 382
class Solution:
# 从链表头开始,遍历整个链表,对遍历到的第 i 个节点,随机选择区间 [0,i) 内的一个整数,如果其等于 0,
# 则将答案置为该节点值,否则答案不变。
def __init__(self, head: Optional[ListNode]):
self.head = head
def getRandom(self) -> int:
node = self.head
i = 1
ans = 0
while node:
if random.randrange(i) == 0:
ans = node.val
i += 1
node = node.next
return ans
共n个节点,对于第i个节点,被选中的总概率是 1/i * (1 - 1/(i+1)) * (1 - 1/(i+2)) * … (1 - 1/n) = 1/n
首项 1/i 是 选中i的概率,后面每一项是 [i+1,n] 项没有被选中的概率 (i未被覆盖)