返回

LeetCode 710:黑名单中的随机数,官方解题思路详解

Android

前言

在 LeetCode 浩瀚的题海中,第 710 题「黑名单中的随机数」以其巧妙的解题思路著称。本文将以独到的视角,为您揭开官方解题思路的神秘面纱,带您领略算法世界中的智慧与优雅。

背景

想象一下,你有两个集合:

  • 一个包含 N 个元素的数组 nums
  • 一个黑名单,其中包含 blacklist 个元素。

现在,你需要实现一个方法,它将从 nums 中随机选择一个元素,但不能选择出现在黑名单中的元素。

官方解题思路

官方解题思路的关键在于将黑名单中的元素映射到 nums 中非黑名单元素的位置上。

具体步骤如下:

  1. 初始化一个映射表 map,将黑名单中的元素映射到 -1。
  2. 从左到右遍历 nums,对于每一个元素 nums[i]
    • 如果 nums[i] 在黑名单中(即 map[nums[i]] 为 -1),则跳过。
    • 否则,如果 i 等于黑名单中的元素,则将其映射到 map[nums[i]] 中。
  3. 返回 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 题「黑名单中的随机数」是一个经典的算法问题,官方解题思路充分体现了算法设计中的巧思和严谨。通过深入理解本题,我们不仅掌握了解决特定问题的技巧,更能领会算法设计的一般性原则。

我希望这篇文章能为您提供清晰的思路,助力您在算法学习的道路上不断进步。