返回
LeetCode 710:黑名单中的随机数,官方解题思路详解
Android
2024-01-14 15:41:03
前言
在 LeetCode 浩瀚的题海中,第 710 题「黑名单中的随机数」以其巧妙的解题思路著称。本文将以独到的视角,为您揭开官方解题思路的神秘面纱,带您领略算法世界中的智慧与优雅。
背景
想象一下,你有两个集合:
- 一个包含 N 个元素的数组
nums
。 - 一个黑名单,其中包含
blacklist
个元素。
现在,你需要实现一个方法,它将从 nums
中随机选择一个元素,但不能选择出现在黑名单中的元素。
官方解题思路
官方解题思路的关键在于将黑名单中的元素映射到 nums
中非黑名单元素的位置上。
具体步骤如下:
- 初始化一个映射表
map
,将黑名单中的元素映射到 -1。 - 从左到右遍历
nums
,对于每一个元素nums[i]
:- 如果
nums[i]
在黑名单中(即map[nums[i]]
为 -1),则跳过。 - 否则,如果
i
等于黑名单中的元素,则将其映射到map[nums[i]]
中。
- 如果
- 返回
nums
中非黑名单元素的随机索引。
代码实现
import random
class Solution:
def __init__(self, n: int, blacklist: List[int]):
self.n = n
self.map = {}
for num in blacklist:
self.map[num] = -1
self.m = n - len(blacklist)
def pick(self) -> int:
while True:
idx = random.randint(0, self.n - 1)
if idx not in self.map:
return idx
else:
target = self.map[idx]
if target == -1:
continue
else:
self.map[idx] = target
关键要点
- 映射黑名单元素: 通过映射表,将黑名单元素映射到
nums
中非黑名单元素的位置上。 - 随机索引: 从
nums
中非黑名单元素的范围内随机选择一个索引。 - 防止无限循环: 在映射过程中,如果
nums[i]
恰好等于黑名单元素,则将map[nums[i]]
映射到nums
中下一个非黑名单元素的位置。
优势
官方解题思路具有以下优势:
- 时间复杂度为 O(N): 遍历
nums
一次,空间复杂度为 O(N)。 - 算法简单: 代码易于理解和实现。
- 泛化性强: 该方法可以推广到其他类似问题,如「从有序数组中随机选择 K 个不重复的元素」。
总结
LeetCode 710 题「黑名单中的随机数」是一个经典的算法问题,官方解题思路充分体现了算法设计中的巧思和严谨。通过深入理解本题,我们不仅掌握了解决特定问题的技巧,更能领会算法设计的一般性原则。
我希望这篇文章能为您提供清晰的思路,助力您在算法学习的道路上不断进步。