在O(1)中设计支持min,getLast,append,deleteLast的数据结构,由n(不是O(n))+ O(1)限定的内存

时间:2015-08-18 17:12:23

标签: algorithm data-structures

我需要设计一个支持以下内容的数据结构:

getMinElementgetLastElementinsertElementdeleteLastElement - 在O(1)运行时间内。

存储器受n (非O(n))的限制,即您可以在给定时刻保留最多n个元素。再加上O(1)记忆。

(重要的是:指针也被视为1,因此链接列表是不可能的。)

示例:

insert(6)
min() -> 6
insert(10)
insert(5)
min() -> 5
insert(7)
delete()
min() -> 5
delete()
min() -> 6

3 个答案:

答案 0 :(得分:4)

我们会直接存储最近的最小值。这是O(1)空间。

我们还将使用整数数组,因为这似乎是我们对可变长度空间的唯一选择。但我们不会直接存储这些元素。相反,当我们插入一个元素时,我们将存储该元素与(先前)最小值之间的差异。当我们删除一个元素时,如果需要,我们可以使用该差异恢复先前的最小值。

在Python中:

class MinStorage:

    def __init__(self):
        self.offsets = []
        self.min = None

    def insertElement(self, element):
        offset = 0 if self.min is None else (element - self.min)
        self.offsets.append(offset)
        if self.min is None or offset < 0:
            self.min = element

    def getMinElement(self):
        return self.min

    def getLastElement(self):
        offset = self.offsets[-1]
        if offset < 0:
            # Last element defined a new minimum, so offset is an offset
            # from the prior minimum, not an offset from self.min.
            return self.min
        else:
            return self.min + offset

    def deleteLastElement(self):
        offset = self.offsets[-1]
        self.offsets.pop()
        if len(self.offsets) == 0:
            self.min = None
        if offset < 0:
            self.min -= offset

这是一个版本,它允许任何无符号的16位整数作为元素,并且只在数组中存储无符号的16位整数:

class MinStorage:

    Cap = 65536

    def __init__(self):
        self.offsets = []
        self.min = None

    def insertElement(self, element):
        assert 0 <= element < self.Cap
        offset = 0 if self.min is None else (element - self.min)
        if offset < 0: offset += self.Cap
        self.offsets.append(offset)
        if self.min is None or element < self.min:
            self.min = element

    def getMinElement(self):
        return self.min

    def getLastElement(self):
        element = self.__getLastElementUnchecked()
        if element < self.min:
            # Last element defined a new minimum, so offset is an offset
            # from the prior minimum, not an offset from self.min.
            return self.min
        else:
            return element

    def deleteLastElement(self):
        element = self.__getLastElementUnchecked()
        self.offsets.pop()
        if len(self.offsets) == 0:
            self.min = None
        elif element < self.min:
            # Popped element defined a new minimum.
            self.min = element

    def __getLastElementUnchecked(self):
        offset = self.offsets[-1]
        element = self.min + offset
        if element >= self.Cap:
            element -= self.Cap
        return element

请注意,在包含溢出/下溢的无符号16位算术的语言中,您不需要涉及self.Cap的检查和调整。在C(§6.2.5/ 9)和C ++(§3.9.1/ 4)中,无符号算术需要根据需要运行。但是,Python不支持无符号16位算术。

答案 1 :(得分:1)

使用存储插入值和当前最小值的堆栈。插入(推送)值时,通过将值与当前最小值进行比较,以及从堆栈顶部删除(弹出)一个查看当前最小值的值,可以更新当前最小值。

答案 2 :(得分:0)

如果您可以假设类似&#34;数据的范围是0到255(int8)&#34;,并且您可以存储精度两倍的整数(int16),那么您可以存储&#34;累计最低值&#34;在高位字节和低位字节的数据点。除了这样的事情之外,我不相信这可以在你给出的限制范围内实现。