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

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. 性能测试中TPS上不去的原因

    TPS(Transaction Per Second):每秒事务数,指服务器在单位时间内(秒)可以处理的事务数量,一般以request/second为单位. 压测中为什么TPS上不去的原因: .网络带 ...

  2. iOS -实现UIView圆角显示的方法

    添加一个UIView时,默认直角显示有时对于有强迫症的患者还真有点不舒服! eg: 怎么实现UIview的圆角显示呢? 首先包含一个头文件: #import <QuartzCore/Quartz ...

  3. Android开发之StrictMode

    StrictMode简介 Android开发者官网对StrictMode的介绍 StrictMode类是Android 2.3(API 9)引入的一个工具类 用来帮助开发者发现代码中一些不规范的问题, ...

  4. 【JAVA进阶架构师指南】之五:JVM性能调优

    前言   首先给大家说声对不起,最近属实太忙了,白天上班,晚上加班,回家还要收拾家里,基本每天做完所有事儿都是凌晨一两点了,没有精力再搞其他的了.   好了,进入正题,让我们来聊聊JVM篇最后一个章节 ...

  5. (五)pom文件详解

    <?xml version="1.0" encoding="UTF-8"?> <!--是所有pom.xml的根元素,并且在里面定义了命名空间和 ...

  6. java并发编程系列原理篇--JDK中的通信工具类Semaphore

    前言 java多线程之间进行通信时,JDK主要提供了以下几种通信工具类.主要有Semaphore.CountDownLatch.CyclicBarrier.exchanger.Phaser这几个通讯类 ...

  7. CKA考试个人心得分享

    考试相关准备: 真题:需要的私密: 网络:必须开启VPN,以便能访问国外网络,强烈建议在香港搭建相应FQ: 证件:考试需要出示含有拉丁文(英文)带照片的有效证件,相关有效证件参考(优先建议护照):ht ...

  8. Android开发学习笔记Intent 一

    Inten的概念 1.Intent是Android四大组件直接沟通的桥梁 2.Intent是一种运行时绑定(runtime binding)机制 Intent对象的属性 Itent的种类 Inten过 ...

  9. WIN10下如何解决PL2303驱动不可用的问题或者com口显示黄色感叹号usb-to-serial

    WIN10下如何解决PL2303驱动不可用的问题或者com口显示黄色感叹号usb-to-serial

  10. 玩Python小游戏猜数字,在游戏中掌握基础,你还能学不会?

    学python怎么离得开案例呢? 今天再继续给大家分享一个Python教程里的猜数字游戏     我最近也是在学python,从事编程工作几年了,但是python还是今年才开始玩的,不得不说,这真是一 ...