当前位置: 首页 > news >正文

LeetCode 380 - O(1) 时间插入、删除和获取随机元素

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 代码解析
    • 示例测试及结果
      • 运行结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

在很多系统设计里,我们经常会遇到“集合”这种数据结构:它需要支持快速插入、删除和查找操作。但有时候,还会额外要求一个功能——随机获取集合里的元素,并且每个元素都有相同的概率被返回。

LeetCode 第 380 题就是这样一个有意思的问题:设计一个数据结构,能够在 平均 O(1) 的时间内完成 插入、删除、随机获取 三个操作。本文会从需求出发,带你一步步拆解这道题,并写出可运行的 Swift 代码。

描述

题目要求实现一个类 RandomizedSet,包含以下方法:

  1. insert(val)

    • 如果 val 不存在,插入集合并返回 true;否则返回 false
  2. remove(val)

    • 如果 val 存在,从集合中删除并返回 true;否则返回 false
  3. getRandom()

    • 从集合中等概率返回一个元素。

要求:每个操作的平均时间复杂度必须是 O(1)

示例运行效果:

输入
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]输出
[null, true, false, true, 2, true, false, 2]

题解答案

直觉上,如果只用数组,随机获取很方便,但删除就可能是 O(n),因为要移动元素。
如果只用哈希表,插入和删除很快,但随机取元素就不好办。

所以,我们需要结合 数组 + 哈希表 的优点:

  • 数组(list):方便随机访问,getRandom() 可以在 O(1) 时间完成。
  • 哈希表(dict/map):存储每个元素在数组中的索引,保证 insertremove 能在 O(1) 完成。

关键技巧是:

  • 删除时,先把要删除的元素与数组最后一个元素交换位置,然后删除最后一个元素,就能避免 O(n) 的移动操作。

题解代码分析

下面是 Swift 的完整实现:

import Foundationclass RandomizedSet {private var dict: [Int: Int]  // 记录 val -> indexprivate var list: [Int]       // 存储元素数组init() {dict = [:]list = []}// 插入操作func insert(_ val: Int) -> Bool {if dict[val] != nil {return false}list.append(val)dict[val] = list.count - 1return true}// 删除操作func remove(_ val: Int) -> Bool {guard let index = dict[val] else {return false}let last = list.last!// 把最后一个元素放到 index 位置list[index] = lastdict[last] = index// 删除最后一个元素list.removeLast()dict.removeValue(forKey: val)return true}// 随机获取func getRandom() -> Int {return list.randomElement()!}
}

代码解析

  1. dict 哈希表

    • 记录每个元素在数组中的位置,保证 O(1) 查找。
  2. list 数组

    • 存放所有元素,支持 O(1) 随机访问。
  3. insert(val)

    • 如果元素已存在,直接返回 false
    • 否则,把元素插入数组尾部,同时在 dict 中记录索引。
  4. remove(val)

    • 查找元素索引,如果不存在,返回 false
    • 如果存在,把该元素与数组最后一个元素交换,更新哈希表,然后删除数组尾部。
    • 这样避免了 O(n) 的删除操作。
  5. getRandom()

    • 直接用 Swift 内置的 randomElement() 从数组中等概率获取一个元素。

示例测试及结果

我们来写一段 Demo 测试一下:

let randomizedSet = RandomizedSet()print(randomizedSet.insert(1))  // true
print(randomizedSet.remove(2))  // false
print(randomizedSet.insert(2))  // true
print(randomizedSet.getRandom())// 1 或 2
print(randomizedSet.remove(1))  // true
print(randomizedSet.insert(2))  // false (因为 2 已存在)
print(randomizedSet.getRandom())// 必然是 2

运行结果

true
false
true
2
true
false
2

效果和题目描述完全一致。

时间复杂度

  • insert: O(1)
  • remove: O(1)
  • getRandom: O(1)

因此整体时间复杂度就是 O(1)

空间复杂度

  • 使用了一个数组 list 和一个哈希表 dict,都最多存储 n 个元素。
  • 空间复杂度为 O(n)

总结

这道题的精髓在于 数组 + 哈希表 的巧妙组合:

  • 数组让我们能快速获取随机元素;
  • 哈希表让我们能快速查找元素位置;
  • 删除操作通过“交换 + 删除尾部”优化到 O(1)。

在实际开发中,这种设计思路同样很实用,比如:

  • 游戏中随机抽卡系统(快速插入、移除、随机获取奖励项);
  • 缓存系统中随机淘汰策略(随机挑选一个元素删除);
  • 动态集合管理(需要等概率抽取元素)。

文章转载自:

http://cv0YZnjt.kmjbs.cn
http://VUHPh38D.kmjbs.cn
http://02l597T5.kmjbs.cn
http://qhnjIo5j.kmjbs.cn
http://UH2WHvjX.kmjbs.cn
http://mZEzUzpM.kmjbs.cn
http://aAinsvK4.kmjbs.cn
http://elDguh5f.kmjbs.cn
http://NjSlgpX0.kmjbs.cn
http://GZrpkcK2.kmjbs.cn
http://IKsj4VLz.kmjbs.cn
http://lp8Npcwu.kmjbs.cn
http://1Q6GBezv.kmjbs.cn
http://yebpHE5q.kmjbs.cn
http://rJta4HpH.kmjbs.cn
http://MRq92zBx.kmjbs.cn
http://ehqB0wTq.kmjbs.cn
http://XWSgBXB2.kmjbs.cn
http://RcTesi7a.kmjbs.cn
http://lup6CZfH.kmjbs.cn
http://eVmnxKQz.kmjbs.cn
http://N1Cn61c2.kmjbs.cn
http://r8EneEab.kmjbs.cn
http://50rzmoPm.kmjbs.cn
http://HQUOYPgJ.kmjbs.cn
http://R57zV3pC.kmjbs.cn
http://rMDjJqpq.kmjbs.cn
http://rNTQZTAO.kmjbs.cn
http://VDYHOcTl.kmjbs.cn
http://IIDKf9rY.kmjbs.cn
http://www.dtcms.com/a/386024.html

相关文章:

  • 9 基于机器学习进行遥感影像参数反演-以随机森林为例
  • DB Hitek宣布推出650V GaN HEMT工艺
  • 机器学习简单数据分析案例
  • [特殊字符] 欢迎使用 C++ Arrow 函数 - 革命性的新特性!
  • 外网访问分布式跟踪系统 zipkin
  • Base 发币在即:L2 代币能否撬动生态增长?
  • DRDR生态Token正式上线BitMart,开启全球化新篇章
  • Spring Boot 3 + EasyExcel 文件导入导出实现
  • 9.16总结
  • Android开机时间查看
  • 探针水平的表达矩阵转换为基因水平的表达矩阵是芯片数据分析中关键的一步
  • PHP基础-语法初步(第七天)
  • 奥威BI与ChatBI:自然语言交互赋能企业数据分析新体验
  • Vue: 组件基础
  • 亚马逊云科技 EC2 服务终端节点:安全高效访问云服务的利器
  • 2026届计算机毕业设计选题 大数据毕业设计选题推荐 题目新颖 数据分析 可视化大屏 通过率高
  • html实现文字横向对齐以及margin的解释
  • 如何轻松找到并畅玩Edge浏览器隐藏的冲浪小游戏
  • K8S中的神秘任务Job与CronJob
  • go grpc开发使用
  • [论文阅读] 人工智能 + 软件工程 | 告别冗余HTML与高算力消耗:EfficientUICoder如何破解UI2Code的token难题
  • Golang语言入门篇004_Go命令详解
  • K8S的Pod状态处理指南
  • Gin框架:构建高性能Go Web应用
  • Golang中的NaN(Not a Number)
  • golang 做webrtc开发核心
  • Go语言中 error 接口与自定义错误类型的深入解析
  • D008 vue+django+neo4j基于知识图谱的政务服务搜索推荐系统
  • 一个高精度通用模板
  • Flink 1.17.2 集群安装部署