📜  门| GATE CS 2018 |简体中文问题30(1)

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

门| GATE CS 2018 |简体中文问题30

本题是2018年计算机科学领域的门考题,属于高难度问题。题目如下:

设计一种数据结构,支持以下操作:

  1. void insert(int key): 插入一个新的key。如果key已存在,则不做任何操作。

  2. void delete(int key): 删除一个key。如果key不存在,则不做任何操作。

  3. int getRandom(): 随机返回一个已经存在的key,每个key被返回的概率相等。

所有操作均需完成,且时间复杂度应为O(1)。

思路分析

该问题需要设计一种数据结构,同时支持三种操作,且复杂度为O(1)。我们可以使用哈希表和动态数组进行结合。

哈希表可以实现插入和删除操作的O(1)时间复杂度。但要随机返回一个已存在的key并不容易。因此,我们可以将元素存入一个动态数组中,并记录每个元素在数组中的位置。这样,随机返回一个元素就转化为随机获取一个数组下标。

为了保证插入的key不重复,我们需要在插入之前进行查找。如果key已经存在,直接返回。如果不存在,则插入到哈希表中,并将元素添加到数组中。

在删除操作时,我们需要先将哈希表中对应的键删除,然后将数组中对应位置的元素和数组尾部的元素进行交换,并删除数组尾部的元素,同时更新被交换元素的新下标。

最后,随机返回一个元素就是随机返回一个数组下标对应的元素。

代码实现

实现代码如下:

class RandomizedSet:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self._nums = []  # 动态数组
        self._pos = {}  # 字典,key为数字,value为数字所在动态数组位置的下标

    def insert(self, val: int) -> bool:
        """
        Inserts a value to the set. Returns true if the set did not already contain the specified element.
        """
        if val in self._pos:
            return False
        self._nums.append(val)
        self._pos[val] = len(self._nums) - 1
        return True

    def remove(self, val: int) -> bool:
        """
        Removes a value from the set. Returns true if the set contained the specified element.
        """
        if val not in self._pos:
            return False
        pos = self._pos[val]
        last = self._nums[-1]
        self._nums[pos], self._nums[-1] = self._nums[-1], self._nums[pos]
        self._nums.pop()
        self._pos[last] = pos
        del self._pos[val]
        return True

    def getRandom(self) -> int:
        """
        Get a random element from the set.
        """
        return self._nums[random.randint(0, len(self._nums) - 1)]

以上代码使用了Python语言实现,整体结构为一个类,在初始化函数中,创建了一个列表用于存放key,并创建一个字典用于存放key所在的列表下标,方便查找和删除操作。

在插入操作中,使用了列表的append方法,将新的元素添加到列表中,并使用字典将它的值映射到列表的下标位置上。

在删除操作中,首先在字典中查找是否存在要删除的key,如果不存在直接返回False。如果存在,先通过字典在列表中找到该元素的下标位置,将它和列表的最后一个元素交换位置,然后再弹出列表最后一个元素。在交换位置和删除元素之后,需要更新字典中数组尾部元素的新下标。

随机返回元素操作比较简单,只需要在列表中随机选择一个下标,然后返回该下标对应的元素即可。

代码实现中,插入和删除操作的时间复杂度为O(1),取随机元素的操作也是O(1)。因此,整个数据结构的操作复杂度为O(1)。

返回markdown格式

以上是本题思路的实现代码,实现了题目所需要的三个操作,并满足时间复杂度为O(1)的要求。如果您需要使用markdown格式来描述这个问题的解决方法,可以使用以下格式:

门| GATE CS 2018 |简体中文问题30

思路分析

该问题需要设计一种数据结构,同时支持三种操作,且复杂度为O(1)。我们可以使用哈希表和动态数组进行结合。

哈希表可以实现插入和删除操作的O(1)时间复杂度。但要随机返回一个已存在的key并不容易。因此,我们可以将元素存入一个动态数组中,并记录每个元素在数组中的位置。这样,随机返回一个元素就转化为随机获取一个数组下标。

为了保证插入的key不重复,我们需要在插入之前进行查找。如果key已经存在,直接返回。如果不存在,则插入到哈希表中,并将元素添加到数组中。

在删除操作时,我们需要先将哈希表中对应的键删除,然后将数组中对应位置的元素和数组尾部的元素进行交换,并删除数组尾部的元素,同时更新被交换元素的新下标。

最后,随机返回一个元素就是随机返回一个数组下标对应的元素。

代码实现

以下是Python语言的实现代码:

class RandomizedSet:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self._nums = []  # 动态数组
        self._pos = {}  # 字典,key为数字,value为数字所在动态数组位置的下标

    def insert(self, val: int) -> bool:
        """
        Inserts a value to the set. Returns true if the set did not already contain the specified element.
        """
        if val in self._pos:
            return False
        self._nums.append(val)
        self._pos[val] = len(self._nums) - 1
        return True

    def remove(self, val: int) -> bool:
        """
        Removes a value from the set. Returns true if the set contained the specified element.
        """
        if val not in self._pos:
            return False
        pos = self._pos[val]
        last = self._nums[-1]
        self._nums[pos], self._nums[-1] = self._nums[-1], self._nums[pos]
        self._nums.pop()
        self._pos[last] = pos
        del self._pos[val]
        return True

    def getRandom(self) -> int:
        """
        Get a random element from the set.
        """
        return self._nums[random.randint(0, len(self._nums) - 1)]

以上代码使用了Python语言实现,整体结构为一个类,在初始化函数中,创建了一个列表用于存放key,并创建一个字典用于存放key所在的列表下标,方便查找和删除操作。

在插入操作中,使用了列表的append方法,将新的元素添加到列表中,并使用字典将它的值映射到列表的下标位置上。

在删除操作中,首先在字典中查找是否存在要删除的key,如果不存在直接返回False。如果存在,先通过字典在列表中找到该元素的下标位置,将它和列表的最后一个元素交换位置,然后再弹出列表最后一个元素。在交换位置和删除元素之后,需要更新字典中数组尾部元素的新下标。

随机返回元素操作比较简单,只需要在列表中随机选择一个下标,然后返回该下标对应的元素即可。

代码实现中,插入和删除操作的时间复杂度为O(1),取随机元素的操作也是O(1)。因此,整个数据结构的操作复杂度为O(1)。