📌  相关文章
📜  设计一个支持常量时间插入、删除、搜索和getRandom的数据结构(1)

📅  最后修改于: 2023-12-03 15:28:08.664000             🧑  作者: Mango

设计一个支持常量时间插入、删除、搜索和getRandom的数据结构

介绍

在编写程序时,常常需要使用数据结构来实现高效的算法。在某些情况下,我们需要一种数据结构来支持常量时间的插入、删除、搜索和随机访问操作。

本篇文章将介绍一种数据结构:哈希表。哈希表是一种理论上可以实现常量时间复杂度的数据结构,它具有以下优点:

  • 插入、删除、搜索的时间复杂度都是 O(1)。
  • 可以支持随机访问,即 getRandom 操作。
  • 可以动态扩容,使得哈希表的大小可以随着数据的增加自动扩展。
哈希表

哈希表是一种基于哈希函数实现的数据结构,它包含了两个重要的部分:哈希函数和哈希表数组。

哈希函数

哈希函数是将输入映射到哈希表数组索引的一种函数。一般来说,哈希函数应该满足以下条件:

  • 输出的哈希值应该能够唯一标识输入的数据。
  • 哈希函数的计算时间应该是 O(1) 的。
哈希表数组

哈希表数组是一个定长数组,它的每个元素都是一个链表或者红黑树。在哈希表中,元素被插入到不同的链表或红黑树中,每个链表或红黑树被称为一个桶。

哈希表的工作流程如下:

  • 根据输入的数据,哈希函数将其映射为一个哈希值。
  • 哈希值对数组长度取模,得到该数据在数组中的下标。
  • 在该下标对应的桶中搜索该数据。

如果需要在哈希表中插入一个数据,可以按照上述流程计算它在数组中的位置,并插入到该位置对应的桶中。如果需要从哈希表中删除一个数据,也可以按照相同的流程计算它在数组中的位置,并从该位置的桶中删除。

实现

下面是一个简单的哈希表实现,它包含了插入、删除、搜索和 getRandom 四种操作,并且满足了时间复杂度为 O(1) 的要求。

import random

class RandomizedSet:
    def __init__(self):
        self.hash_map = {}
        self.lst = []

    def insert(self, val: int) -> bool:
        if val not in self.hash_map:
            self.hash_map[val] = len(self.lst)
            self.lst.append(val)
            return True
        return False

    def remove(self, val: int) -> bool:
        if val in self.hash_map:
            idx = self.hash_map[val]
            last = self.lst[-1]
            self.hash_map[last] = idx
            self.lst[idx] = last
            self.lst.pop()
            del self.hash_map[val]
            return True
        return False

    def getRandom(self) -> int:
        return random.choice(self.lst)

该哈希表使用了一个字典和一个数组来实现,其中字典用于存储每个数据的索引,数组用于存储数据本身。插入操作将数据插入到数组的末尾,并记录该数据在数组中的索引。搜索操作会根据哈希函数计算该数据在数组中的位置,并在该位置的链表或红黑树中搜索该数据。

删除操作需要将数组中最后一个元素与需要删除的元素交换,然后将数组的长度减一,并且更新字典中最后一个元素的索引。这样做的好处是,删除操作的时间复杂度可以保证是 O(1) 的。

随机访问操作可以通过 random.choice() 函数直接返回数组中的一个随机元素。

总结

哈希表是一种非常重要且常用的数据结构,它可以支持常量时间的插入、删除、搜索和随机访问操作。在使用哈希表时,需要注意哈希函数的设计和哈希冲突的处理,以保证哈希表的正确性和高效性。