首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

删除Map()中最旧的条目,时间复杂度为O(1) JS

在JavaScript中,Map是一种数据结构,用于存储键值对的集合。如果要删除Map中最旧的条目,并且要求时间复杂度为O(1),可以使用以下方法:

  1. 使用Map结合双向链表:创建一个Map对象,并在每个键值对中添加一个时间戳属性。同时,使用一个双向链表来维护键值对的顺序,最旧的条目位于链表的头部。这样,当需要删除最旧的条目时,只需通过链表头部获取最旧的键,然后通过Map的delete方法删除该键值对。由于链表头部的访问是O(1)的操作,所以删除操作的时间复杂度为O(1)。

以下是一个示例代码:

代码语言:txt
复制
class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.map = new Map();
    this.head = null;
    this.tail = null;
  }

  get(key) {
    if (this.map.has(key)) {
      const node = this.map.get(key);
      this.moveToHead(node);
      return node.value;
    }
    return -1;
  }

  put(key, value) {
    if (this.map.has(key)) {
      const node = this.map.get(key);
      node.value = value;
      this.moveToHead(node);
    } else {
      const newNode = { key, value, prev: null, next: null };
      if (this.map.size >= this.capacity) {
        this.removeTail();
      }
      this.addToHead(newNode);
      this.map.set(key, newNode);
    }
  }

  moveToHead(node) {
    if (node === this.head) {
      return;
    }
    if (node.prev) {
      node.prev.next = node.next;
    }
    if (node.next) {
      node.next.prev = node.prev;
    }
    if (node === this.tail) {
      this.tail = node.prev;
    }
    node.prev = null;
    node.next = this.head;
    if (this.head) {
      this.head.prev = node;
    }
    this.head = node;
  }

  removeTail() {
    if (!this.tail) {
      return;
    }
    this.map.delete(this.tail.key);
    if (this.tail.prev) {
      this.tail.prev.next = null;
    } else {
      this.head = null;
    }
    this.tail = this.tail.prev;
  }

  addToHead(node) {
    node.next = this.head;
    if (this.head) {
      this.head.prev = node;
    }
    this.head = node;
    if (!this.tail) {
      this.tail = node;
    }
  }
}

const cache = new LRUCache(5);
cache.put("key1", "value1");
cache.put("key2", "value2");
cache.put("key3", "value3");
cache.put("key4", "value4");
cache.put("key5", "value5");

console.log(cache.get("key3")); // 输出:value3
console.log(cache.get("key1")); // 输出:value1

cache.put("key6", "value6"); // 删除最旧的条目

console.log(cache.get("key2")); // 输出:-1,已被删除
console.log(cache.get("key6")); // 输出:value6

在上述示例代码中,LRUCache类实现了一个基于LRU(最近最少使用)算法的缓存。LRUCache类使用了Map来存储键值对,并使用双向链表来维护键值对的顺序。通过在每个键值对中添加时间戳属性,并使用双向链表来维护顺序,可以实现删除最旧条目的O(1)时间复杂度。

腾讯云相关产品和产品介绍链接地址:

  • 云服务器(CVM):提供可扩展的计算容量,满足各种业务需求。产品介绍链接
  • 云数据库 MySQL 版(CMYSQL):高性能、可扩展的关系型数据库服务。产品介绍链接
  • 云存储(COS):安全可靠、高扩展性的云端存储服务。产品介绍链接
  • 人工智能(AI):提供丰富的人工智能服务和解决方案,包括图像识别、语音识别、自然语言处理等。产品介绍链接
  • 物联网(IoT):提供全面的物联网解决方案,包括设备接入、数据管理、应用开发等。产品介绍链接
  • 云原生应用引擎(TKE):用于构建和管理容器化应用的托管服务。产品介绍链接
  • 腾讯云区块链服务(TBC):提供一站式区块链解决方案,包括区块链网络搭建、智能合约开发等。产品介绍链接
  • 腾讯云元宇宙(Tencent Cloud Metaverse):提供全面的元宇宙解决方案,包括虚拟现实、增强现实、三维建模等。产品介绍链接
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

O(1)时间复杂度删除链表节点

前言 有一个单向链表,给定了头指针和一个节点指针,如何在O(1)时间删除该节点?本文将分享一种实现思路来解决这个问题,欢迎各位感兴趣开发者阅读本文。...如果其下一个节点之后还有节点,那我们只需要获取那个节点,将其指针指向获取到节点即可,如下图所示: image-20220210213628642 通过上述思路我们在O(1)时间删除了给定节点,...时间复杂度分析:对于n-1个非尾节点而言,我们可以在O(1)时间内利用节点覆盖法实现删除,但是对于尾节点而言,我们仍然需要按序遍历来删除节点,时间复杂度O(n)。...那么,总时间复杂度就为:[(n-1) * O(1) + O(n)] / n,最终结果还是 O(1),符合题目要求。...如果链表只有一个节点,而我们又要删除链表头节点(也是尾节点),那么,此时我们在删除节点之后还需要把链表头节点设置null。

67830

O(1)时间复杂度删除单链表某个节点

给定链表头指针和一个结点指针,在O(1)时间删除该结点。...一般单链表删除某个节点,需要知道删除节点前一个节点,则需要O(n)遍历时间,显然常规思路是不行。...在仔细看题目,换一种思路,既然不能在O(1)得到删除节点前一个元素,但我们可以轻松得到后一个元素,这样,我们何不把后一个元素赋值给待删除节点,这样也就相当于是删除了当前元素。...可见,该方法可行,但如果待删除节点最后一个节点,则不能按照以上思路,没有办法,只能按照常规方法遍历,时间复杂度O(n),是不是不符合题目要求呢?...其实我们分析一下,仍然是满足题目要求,如果删除节点前面的n-1个节点,则时间复杂度O(1),只有删除节点最后一个时,时间复杂度O(n),所以平均时间复杂度:(O(1) * (n-1) +

80580

O(1)时间复杂度删除链表节点复制节点

给定一个单链表一个等待被删除节点(非表头或表尾)。请在在O(1)时间复杂度删除该链表节点。...Linked list is 1->2->3->4, and given node 3, delete the node in place 1->2->4 复制节点删除节点一般做法是找到要删除节点前一个节点...,然后把这个节点next指针指向要删除节点下一个节点,一般都是这样做,这个题要求O(1)时间复杂度,显然是不允许遍历搜索,而且给定是节点指针。...我们要删除这个节点,但是我们通过操作只能删除下一个节点,那我们能不能把下一个节点数据拷贝过来到这个节点,然后把下个节点删除,这样就相当于把这个节点删除了 我怎么会想到这个方法呢?...写起来就不是一般简单了,题目中默认此节点不是表头或表尾,所以这种方法是完全可以,如果是表尾的话就不好玩了!

74820

给我 O(1) 时间,我能查找删除数组任意元素

这写问题一个技巧点在于,如何结合哈希表和数组,使得数组删除和查找操作时间复杂度稳定在 O(1)? 下面来一道道看。...: 1、插入,删除,获取随机元素这三个操作时间复杂度必须都是 O(1)。...我们先来分析一下:对于插入,删除,查找这几个操作,哪种数据结构时间复杂度O(1)? HashSet肯定算一个对吧。...这样我们就可以直接生成随机数作为索引,从数组取出该随机索引对应元素,作为随机元素。 但如果用数组存储元素的话,插入,删除时间复杂度怎么可能是 O(1) 呢? 可以做到!...对数组尾部进行插入和删除操作不会涉及数据搬移,时间复杂度O(1)。 所以,如果我们想在 O(1) 时间删除数组某一个元素val,可以先把这个元素交换到数组尾部,然后再pop掉。

1.3K10

LinkedHashMap实现原理(复习)

1. LinkedHashMap概述:    LinkedHashMap是Map接口哈希表和链接列表实现,具有可预知迭代顺序。此实现提供所有可选映射操作,并允许使用null值和null键。...在上述HashMap构造器 ,最后会调用init()方法,进行相关初始化,这个方法在HashMap实现并无意义,只是提供给子类实现相关初始化调用。   ...方法,实际在调用父类getEntry()方法取得查找元素后,再判断当排序模式accessOrdertrue时,记录访问顺序,将最新访问元素添加到双向链表表头,并从原来位置删除。...该方法可以提供在每次添加新条目时移除最旧条目的实现程序,默认返回false,这样,此映射行为将类似于正常映射,即永远不能移除最旧元素。 Java代码   ?...如果用此映射构建LRU缓存,则非常方便,它允许映射通过删除条目来减少内存损耗。    例如:重写此方法,维持此映射只保存100个条目的稳定状态,在每次添加新条目删除最旧条目

64840

基于HashMap+双向列表手写实现LRU算法

LRU算法是一种常用缓存替换策略,它核心思想是在缓存空间不足时,优先淘汰最近最少使用数据。通过维护一个双向链表和一个哈希表,可以在O(1)时间内完成缓存访问、修改和淘汰操作。...简单来说: 最近最少使用,就是把数据加入一个链表,按访问时间排序,发生淘汰时候,把访问时间最旧淘汰掉。...,也就是最右数据最新,但是数据满了之后,会把最旧数据(最近最久)删除 上述代码也可以看到,有个配置,主要设置链表大小,已经Map扩容负载因子,可以直接设置0.75(map扩容默认就是0.75)...思想:LRU算法目的实现读写两个操作,命中O(1) 时间复杂度 设计方案:采用哈希链表,hashmap+双向列表,主要是是因为哈希查找快,链表插入和删除快,利用hash来存储查找数据, 双向链表关联每个元素...HashMap来存储键值对,以实现O(1)时间复杂度查找。

34410

【JUC进阶】12. 环形缓冲区

其大致结构如图: 循环缓冲区有一个指针指向缓冲区下一个空位置,并且我们随着每个新条目递增该指针。这意味着当缓冲区已满时,我们添加一个新元素,它会覆盖最旧元素。...当缓冲区已满时,循环缓冲区不需要移动元素来新数据腾出空间。 相反,当缓冲区已满时,新数据将覆盖最旧数据。将元素添加到循环缓冲区时间复杂度是常数 O(1)。...这使得它在我们必须快速添加和删除数据实时系统中非常高效。 2.2、结构刨析 循环缓冲区有两个指针,一个指向缓冲区头部(head),另一个指向缓冲区尾部(tail)。...头指针指向我们将插入下一个元素位置,尾指针指向缓冲区中最旧元素位置。 当头指针和尾指针相遇时,我们认为缓冲区已满。...指针管理复杂:由于环形缓冲区特殊性质,读/写指针需要特殊管理,以确保数据正确性和一致性。这可能会增加代码复杂度,并引入潜在错误风险。

13110

如何动手撸一个LRU缓存

LRU缓存实现相比LFU来说要简单一点,最关键在于LRU缓存插入,查询和删除可以做到O1时间复杂度,这一点相比LFUO(logN)来说在大数据量下LRU表现更好,此外LRU非常适合存在热点数据场景...首先让我们分析下LRU缓存为什么能达到O1时间复杂度。...众所周知,双向链表插入和删除可以达到O1时间复杂度,但双向链表缺点在于,其查询时间复杂度O(n)这就是它短板,那么如何加速查询?...这里我们可以利用HashMap来当索引查询,从而使得双向链表查询时间复杂度也能达到O1),没错LRU实现原理,就是充分结合了两种数据结构优点而衍生出来。...我们首先判断要插入key是否存在,如果存在就删除掉,方便将其移动到链表头部位置,接着我们判断缓存容量是否超出指定大小,如果超出就要淘汰最旧数据,也就是位于链表尾部(尾部是虚拟节点前一个节点

60920

实现一个LRU真的好难呐

Map 对象,但是在最坏情况下,如果哈希函数分布不均匀,可能会导致哈希冲突,使得某些操作时间复杂度变为 O(n)。...插入 {key: 11, value: 'f'} 注意,在将键 6 和 11 键值对插入哈希表时,它们都被映射到索引 1 。...这是因为它们分别与 1 余数相同。 当出现哈希冲突时,即多个键被映射到同一桶时 这种情况下,在操作时需要遍历整个桶来查找指定键值对,因此操作时间复杂度变为 O(n)。...双向链表+哈希表 那么如何达到O(1)时间复杂度呢? 那肯定选用 map 查询。修改,删除也要尽量 O(1) 完成。搜寻常见数据结构,链表,栈,队列,树,图。...树和图排除,栈和队列无法任意查询中间元素,也排除。所以选用链表来实现。但是如果选用单链表,删除这个结点,需要 O(n) 遍历一遍找到前驱结点。所以选用双向链表,在删除时候也能 O(1) 完成。

47140

设计实现一个LRU Cache1 什么是LRU Cache2 实现思路

可能大多数人都会想到:用一个数组来存储数据,给每一个数据项标记一个访问时间戳,每次插入新数据项时候,先把数组存在数据项时间戳自增,并将新数据项时间戳置0并插入到数组。...每次访问数组数据项时候,将被访问数据项时间戳置0。当数组空间已满时,将时间戳最大数据项淘汰。 这种实现思路很简单,但是有什么缺陷呢?...需要不停地维护数据项访问时间戳,另外,在插入数据、删除数据以及访问数据时,时间复杂度都是O(n),数组缺陷凸显无疑 那么有没有更好实现办法呢? 那就是利用链表和HashMap。...,这样做好处是,get/set在不冲突情况下可保证O(1)复杂度 也可通过双向链表保证LRU删除/更新O(1)复杂度 当然可简化head和tail变成一个head节点,成环,这样headnext...指向最旧节点,prev指向最新节点。

1.1K70

使用Java和Python解题:定义栈数据结构,请在该类型实现一个能够得到栈中所含最小元素min函数(时间复杂度应为O1))。

问题描述 定义栈数据结构,请在该类型实现一个能够得到栈中所含最小元素min函数(时间复杂度应为O1))。...解题思路 思路:栈stack保存数据,辅助栈assist保存依次入栈最小数 stack依次入栈,6,5,8,4,3,9 assist依次入栈,6,5,4,3 每次入栈时候,如果入栈元素比assist...栈顶元素小或等于则入栈,否则不入栈。...if min > node or not min: #若待入栈元素值小于栈中最小值或栈空时 self.stack.append(node) #将这个元素分别压入数据栈和辅助栈...== self.assist[-1]: #若数据栈和辅助栈栈顶元素值相等 self.stack.pop() #则分别将这两个栈栈顶元素弹出

86930

理解LinkedHashMap

方法,实际在调用父类getEntry()方法取得查找元素后,再判断当排序模式accessOrdertrue时,记录访问顺序,将最新访问元素添加到双向链表表头,并从原来位置删除。...由于链表增加、删除操作是常量级,故并不会带来性能损失。...它作用是表扩容后,把旧表key重新hash到新。...该方法可以提供在每次添加新条目时移除最旧条目的实现程序,默认返回false,这样,此映射行为将类似于正常映射,即永远不能移除最旧元素。...如果用此映射构建LRU缓存,则非常方便,它允许映射通过删除条目来减少内存损耗。 例如:重写此方法,维持此映射只保存100个条目的稳定状态,在每次添加新条目删除最旧条目

54310

Leetcode No.219 存在重复元素 II(滑动窗口)

return False 复杂度分析 1时间复杂度O(n*min(k,n)) 每次搜索都要花费 O(min(k,n)) 时间,哪怕k比n大,一次搜索也只需比较 n次。...2、空间复杂度O(1) 三、解题思路2(散列表) 【通过】 用散列表来维护这个k大小滑动窗口。 我们需要一个支持在常量时间内完成 搜索,删除,插入 操作数据结构,那就是散列表。...遍历数组,对于每个元素做以下操作: 在散列表搜索当前元素,如果找到了就返回 true。 在散列表插入当前元素。 如果当前散列表大小超过了 k, 删除散列表中最旧元素。...1时间复杂度O(n) 我们会做 n 次 搜索,删除,插入 操作,每次操作都耗费常数时间。...2、空间复杂度O(min(n,k)) 开辟额外空间取决于散列表存储元素个数,也就是滑动窗口大小 O(min(n,k))。

21510

LinkedHashMap源码解析

但迭代结果完全不同。LinkedHashMap对访问调序支持简单实现LRUCache奠定了基础。...所以较HashMap源码,LinkedHashMap就是多加了一些双链表操作(插入、删除、节点挪动到尾部……)。 ? 源码 初始化 ?   ...afterNodeAccess分别在putVal、merge、replace……总之所有有变动地方调用,这以为着map中最新变动值肯定是会在链表尾部,相反最旧就在头部了(需要在构造函数开启accessOrder...LRUCache就是这样一种存储实现,它难点就在于如何高效地剔除掉最旧数据,以及如何维护数据新旧度。   有了LinkedHashMap后,我们就可以很简单实现一个LRUCache。...依赖Linked和HashMap结合,查询时可以从HashMapO(1)时间复杂度查询,数据过期也可以用O(1)时间复杂度从Linked删除

35120

合适以及为何使用最少使用(LFU)缓存与Golang实现

因为它对数时间复杂度处理插入,删除和更新。在这篇文章,我们将介绍另一种实现它方法。 但在我们进入实施之前,让我们看看LFU在哪些情况下比替代品更好。...LFU缓存实现,其运行时间复杂度O1),用于其所有操作,包括插入,访问,和删除(驱逐)。...条目列表删除它: 让我们看看从FrequencyItem条目列表删除CacheItem步骤是什么。...有趣是,在本文中,作者解释说,他们提出方法对于每个操作(插入,查找和删除)都具有O1时间复杂度,因为操作基于哈希表。...此外,链接列表不会增加任何时间复杂度,因为我们不会在任何时候遍历列表 - 我们只是在需要时添加或删除其中节点(这是一个O1)操作)。 总结 在本文中,我们了解了LFU缓存基础知识。

1.8K20

HashMap你真的了解吗?

为此,地图存储了 2 个数据: map大小:表示HashMap条目数。每次添加或删除条目时都会更新此值。...地图只返回第二个值,第一个值在 HashMap “丢失”: 输出:“test1= null test2=test 2”。正如预期那样,Map 无法使用修改后1 检索字符串 1。...和 put() 方法时间复杂度 O(1)。...在最坏情况下(如果大多数数据都在同一个桶),您最终可能会得到 O(n) 时间复杂度。 这是一个视觉示例。第一张图显示了一个倾斜 HashMap,第二张图是一个平衡良好图。...如果在 JAVA 7 上运行相同测试,第一种和第二种情况结果会更糟(因为 put 时间复杂度在 JAVA 7 O(n),而在 JAVA 8 O(log(n))) 使用 HashMap

2.2K30
领券