比起之前那些问计数哈希表的题目,这道题好像更接近哈希表的底层机制

java中hashmap的实现是通过List<Node>,即链表的list,如果链表过长则换为红黑树,如果容量不足(装填因子下)则扩充数组容量。解决冲突的方式是直接接在对应位置的链表上。

首先看看哈希表几个操作的时间复杂度:

HashMap的新增:

  1. 计算key的哈希值
  2. 哈希值作为index,找到对应的数组位置
  3. 如果数组位置为,直接存入
  4. 如果数组位置不为空,遍历该链表,插入末尾

这里考虑理想情况(无冲突),时间复杂度为O1

HashMap的删除,查询都是一样的理解,如果没得冲突,都是O1的复杂度。

如果冲突,可能出现On情况(链表),Ologn情况(红黑树)

返回随机元素,这个则不好实现,因为HashMap是无序的,又没得类似List那样的索引,很难返回一个random的值。

接着考虑的一个方式就是,能不能把HashMap的key以0,1。。。的方式存到一个数组中,用random得到一个随机的序号,然后在通过序号去找。

然而这里犯了一个错误。这样的方式其实无疑与把这个HashMap变成了一个LIst。当然插入是O1,但是删除则不好操作了。

第二个想法是Hashset,但问题其实也一样,这是一个无序的set,没办法搞random。这里的无序set指的是插入进去之后放到的位置就是hash算出来的位置,显然无法用随机的方式使得每一个元素返回的概率相同。

第三个想法则是List作为基础,再用HashMap来补缺陷

LIst的操作复杂度:

  • append,直接在尾端加,O1
  • pop,直接去掉尾端,O1
  • 特定位置插入/删除,都需要萝卜挪坑,On
  • 访问特定位置元素,索引直接访问,O1
  • 查,要跑一遍整个数组,On

所以Random很好做到,其余的需要用append和pop搞事

append需要去重,我们把索引和值分别存入HashMap作为辅助

这样要插入时,先用HashMap判断有无(O1),然后直接插尾端(O1)

删除稍麻烦一些,我们如果直接删除真正位置,则需要挪位置变为On

所以用HashMap找到位置后,将该位置和List末尾做交换,然后PoP,这样就是O1了。

class RandomizedSet {
Map<Integer, Integer> dict;
List<Integer> list;
Random rand = new Random(); /** Initialize your data structure here. */
public RandomizedSet() {
dict = new HashMap();
list = new ArrayList();
} /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
public boolean insert(int val) {
if (dict.containsKey(val)) return false; dict.put(val, list.size());
list.add(list.size(), val);
return true;
} /** Removes a value from the set. Returns true if the set contained the specified element. */
public boolean remove(int val) {
if (! dict.containsKey(val)) return false; // move the last element to the place idx of the element to delete
int lastElement = list.get(list.size() - 1);
int idx = dict.get(val);
list.set(idx, lastElement);
dict.put(lastElement, idx);
// delete the last element
list.remove(list.size() - 1);
dict.remove(val);
return true;
} /** Get a random element from the set. */
public int getRandom() {
return list.get(rand.nextInt(list.size()));
}
}

LeetCode 哈希表 380. 常数时间插入、删除和获取随机元素(设计数据结构 List HashMap底层 时间复杂度)的更多相关文章

  1. Java实现 LeetCode 380 常数时间插入、删除和获取随机元素

    380. 常数时间插入.删除和获取随机元素 设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构. insert(val):当元素 val 不存在时,向集合中插入该项. remove( ...

  2. LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed O(1) 时间插入、删除和获取随机元素 - 允许重复(C++/Java)

    题目: Design a data structure that supports all following operations in averageO(1) time. Note: Duplic ...

  3. LeetCode380 常数时间插入、删除和获取随机元素

    LeetCode380 常数时间插入.删除和获取随机元素 题目要求 设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构. insert(val):当元素 val 不存在时,向集合中插 ...

  4. Java实现 LeetCode 381 O(1) 时间插入、删除和获取随机元素 - 允许重复

    381. O(1) 时间插入.删除和获取随机元素 - 允许重复 设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构. 注意: 允许出现重复元素. insert(val):向集合中插 ...

  5. 381. O(1) 时间插入、删除和获取随机元素 - 允许重复

    381. O(1) 时间插入.删除和获取随机元素 - 允许重复 LeetCode_381 题目详情 题解分析 代码实现 package com.walegarrett.interview; impor ...

  6. Leetcode 381. O(1) 时间插入、删除和获取随机元素 - 允许重复

    1.题目描述 设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构. 注意: 允许出现重复元素. insert(val):向集合中插入元素 val. remove(val):当 va ...

  7. Leetcode 380. 常数时间插入、删除和获取随机元素

    1.题目描述 设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构. insert(val):当元素 val 不存在时,向集合中插入该项. remove(val):元素 val 存在时 ...

  8. LeetCode 380. Insert Delete GetRandom O(1) 常数时间插入、删除和获取随机元素(C++/Java)

    题目: Design a data structure that supports all following operations in averageO(1) time. insert(val): ...

  9. [Swift]LeetCode380. 常数时间插入、删除和获取随机元素 | Insert Delete GetRandom O(1)

    Design a data structure that supports all following operations in averageO(1) time. insert(val): Ins ...

随机推荐

  1. 数据结构&算法

    20个最常用.最基础数据结构与算法: 10个数据结构:数组.链表.栈.队列.散列表.二叉树.堆.跳表.图.Trie 树. 10个 算法      :递归.排序.二分查找.搜索.哈希.贪心.分治.回溯. ...

  2. (四)SQLMap之Tamper篡改脚本的类型、作用、适用场景

    目录结构 一.SQLMap中tamper的简介 1.tamper的作用 2.tamper用法 二.适配不同数据库类型的测试tamper 三.SQLMap中tamper篡改脚本的功能解释 一.SQLMa ...

  3. mysql基础-数据库表简单查询-记录(五)

    0x01 MySQL的查询操作 单表查询:简单查询                 多表查询:连续查询                联合查询 选择和投影 投影:挑选要符合的字段     select ...

  4. Promise相关学习

    what? Promise对象表示一个异步操作的最终状态(完成或失败),以及其返回的值 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/ ...

  5. iOS简历书写注意事项

    1.个人信息模块 1)简历标题 2)姓名 性别  年龄 电话  邮箱  常驻地 学历 英语能力 工作年限 籍贯 专业 (突出优势) 注意:不要从招聘网站导出简历网站 2.求职意向 1)职位 地点 薪资 ...

  6. (二)JavaMail创建包含内嵌图片的邮件

    链接:https://blog.csdn.net/qq_41151659/article/details/96475739 代码如下: import com.sun.mail.util.MailSSL ...

  7. gradle的搭建和配置

    下载 官方网站:https://gradle.org/install/#manually 提供了两种下载方式,Binary-only是只下载二进制源码,Complete, with docs and ...

  8. matplotlib作图一例

    知识点都在这个例子里面: plt.figure(figsize=(10,10)) for i in range(25): plt.subplot(5,5,i+1) plt.xticks([]) plt ...

  9. 消息队列——RabbitMQ的基本使用及高级特性

    文章目录 一.引言 二.基本使用 1. 简单示例 2. work queue和公平消费消息 3. 交换机 三.高级特性 1. 消息过期 2. 死信队列 3. 延迟队列 4. 优先级队列 5. 流量控制 ...

  10. 《Elasticsearch 权威指南》阅读笔记

    书籍地址 https://www.elastic.co/guide/cn/elasticsearch/guide/current/languages.html