Leetcode 432. 全 O(1) 的数据结构
本文最后更新于238 天前,其中的信息可能已经过时,如有错误请发送邮件到2446865563@qq.com

1.题目基本信息

1.1.题目描述

请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。

实现 AllOne 类:

  • AllOne() 初始化数据结构的对象。

  • inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。

  • dec(String key) 字符串 key 的计数减少 1 。如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。

  • getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 "" 。

  • getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 "" 。

注意:每个函数都应当满足 O(1) 平均时间复杂度。

1.2.题目地址

https://leetcode.cn/problems/all-oone-data-structure/description/

2.解题方法

2.1.解题思路

双向链表+哈希表

2.2.解题步骤

请看“注释”

3.解题代码

python代码-方法一(O(1))

class DNode():
    def __init__(self, keys = [], freq = 1):
        self.keys = set(keys)   # 这里用的存储(无需顺序)
        self.freq = freq
        self.prev = None
        self.next = None


class AllOne:
    # 思路:双向链表+哈希表(O(1))
    def __init__(self):
        self.root = self.createNewList()
        self.cache = {}

    # TOOL:创建新链表
    def createNewList(self):
        dumbNode = DNode([], 0)
        dumbNode.next = dumbNode
        dumbNode.prev = dumbNode
        return dumbNode
    
    # TOOL:判断链表是否为空
    def empty(self, node):
        return node.next == node
    
    # TOOL:在prevNode后面插入node节点
    def insertNode(self, prevNode, node):
        node.next = prevNode.next
        node.next.prev = node
        node.prev = prevNode
        prevNode.next = node
    
    # TOOL:删除节点node
    def deleteNode(self, node):
        node.next.prev = node.prev
        node.prev.next = node.next

    def inc(self, key: str) -> None:
        if key in self.cache:
            # 第一步,key在cache中时,保证下一个node.freq+1频率的节点存在;移除node中的key,如果移除后keys长度为0,则将结点一起删除;将key插入node.freq+1频率的节点中,并更新cache
            node = self.cache[key]
            if node.next is self.root or node.next.freq > node.freq + 1:
                self.insertNode(node, DNode([], node.freq + 1))
            node.keys.remove(key)
            if len(node.keys) == 0:
                self.deleteNode(node)
            node.next.keys.add(key)
            self.cache[key] = node.next
        else:
            # 第二步,key不在cache中,保证频率为1的节点存在;然后插入其中并更新cache
            if self.root.next is self.root or self.root.next.freq != 1:
                self.insertNode(self.root, DNode([], freq = 1))
            self.root.next.keys.add(key)
            self.cache[key] = self.root.next

    def dec(self, key: str) -> None:
        # 第一步,如果key不在cache中,直接返回
        if key not in self.cache:
            return
        # 第二步,如果key在cache中;如果node的频数为1,则直接从node.keys中删除并更新cache,如果移除后keys长度为0,则将结点一起删除,并更新cache。如果node的频数大于1,则保证node.freq-1频数的节点存在;再将key插入node.prev节点中,并更新cache;然后从node.keys中移除key,如果移除key后节点的keys为空,则连带节点一起删除
        node = self.cache[key]
        if node.freq == 1:
            node.keys.remove(key)
            if len(node.keys) == 0:
                self.deleteNode(node)
            del self.cache[key] # 并从cache中删除
        else:
            if node.prev is self.root or node.prev.freq != node.freq - 1:
                self.insertNode(node.prev, DNode([], node.freq - 1))
            node.prev.keys.add(key)
            self.cache[key] = node.prev
            node.keys.remove(key)
            if len(node.keys) == 0:
                self.deleteNode(node)
    
    def getMaxKey(self) -> str:
        return  next(iter(self.root.prev.keys)) if self.root.next is not self.root else ""

    def getMinKey(self) -> str:
        return  next(iter(self.root.next.keys)) if self.root.next is not self.root else ""

python代码-方法二(O(length(freqMap)))

class DNode2():
    def __init__(self, key = 0):
        self.key = key
        self.freq = 1
        self.prev = None
        self.next = None


class AllOne1:
    # 思路:双向链表+哈希表(O(len(freqMap)))
    def __init__(self):
        self.cache = {}
        self.freqMap = {}
        self.minFreq = self.maxFreq = 0

    # TOOL:创建新链表
    def createNewList(self):
        dumbNode = DNode(0)
        dumbNode.next = dumbNode
        dumbNode.prev = dumbNode
        return dumbNode
    
    # TOOL:判断链表是否为空
    def empty(self, node):
        return node.next == node
    
    # TOOL:在prevNode后面插入node节点
    def insertNode(self, prevNode, node):
        node.next = prevNode.next
        node.next.prev = node
        node.prev = prevNode
        prevNode.next = node
    
    # TOOL:删除节点node
    def deleteNode(self, node):
        node.next.prev = node.prev
        node.prev.next = node.next

    def inc(self, key: str) -> None:
        # 第一步,保证cache中存在key节点
        if key in self.cache:
            node = self.cache[key]
            node.freq += 1
            self.deleteNode(node)
            if self.empty(self.freqMap[node.freq - 1]):
                del self.freqMap[node.freq - 1]
            if node.freq not in self.freqMap:
                self.freqMap[node.freq] = self.createNewList()
            self.insertNode(self.freqMap[node.freq], node)
        else:
            node = DNode(key)
            self.cache[key] = node
            if node.freq not in self.freqMap:
                self.freqMap[node.freq] = self.createNewList()
            self.insertNode(self.freqMap[node.freq], node)
        # 第二步,更新minFreq和maxFreq(根据是否在freqMap中进行更新)
        # if self.minFreq not in self.freqMap:
        #     self.minFreq = node.freq
        # if node.freq > self.maxFreq:
        #     self.maxFreq = node.freq
        if self.freqMap:
            self.minFreq = min(list(self.freqMap.keys()))
            self.maxFreq = max(list(self.freqMap.keys()))
        else:
            self.minFreq = self.maxFreq = 0

    def dec(self, key: str) -> None:
        # 第一步,保证cache中存在key节点
        if key not in self.cache:
            return
        node = self.cache[key]
        node.freq -= 1
        self.deleteNode(node)
        if self.empty(self.freqMap[node.freq + 1]):
            del self.freqMap[node.freq + 1]
        if node.freq > 0:
            if node.freq not in self.freqMap:
                self.freqMap[node.freq] = self.createNewList()
            self.insertNode(self.freqMap[node.freq], node)
        else:
            del self.cache[key]
        # 第二步,更新minFreq和maxFreq(根据是否在freqMap中进行更新)
        if self.freqMap:
            self.minFreq = min(list(self.freqMap.keys()))
            self.maxFreq = max(list(self.freqMap.keys()))
        else:
            self.minFreq = self.maxFreq = 0
        # if not self.freqMap:
        #     self.minFreq = 0
        # elif self.minFreq not in self.freqMap or self.empty(self.freqMap[self.minFreq]):
        #     self.minFreq = min(list(self.freqMap.keys()))

    def getMaxKey(self) -> str:
        return self.freqMap[self.maxFreq].next.key if self.maxFreq in self.freqMap else ""

    def getMinKey(self) -> str:
        return self.freqMap[self.minFreq].next.key if self.minFreq in self.freqMap else ""

4.执行结果

觉得有帮助可以投喂下博主哦~感谢!

作者:geek007

转载请注明文章地址及作者哦~
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇