栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Leetcode0432. 全 O(1) 的数据结构(difficult)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Leetcode0432. 全 O(1) 的数据结构(difficult)

目录

1. 题目描述

2. 解题分析

2.1 inc()时的更新

2.2 dec()时的更新

3. 代码实现


1. 题目描述


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

实现 AllOne 类:

AllOne() 初始化数据结构的对象。
inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。
dec(String key) 字符串 key 的计数减少 1 。如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。
getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 "" 。
getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 "" 。
 

示例:

输入
["AllOne", "inc", "inc", "getMaxKey", "getMinKey", "inc", "getMaxKey", "getMinKey"]
[[], ["hello"], ["hello"], [], [], ["leet"], [], []]
输出
[null, null, null, "hello", "hello", null, "hello", "leet"]

解释
AllOne allOne = new AllOne();
allOne.inc("hello");
allOne.inc("hello");
allOne.getMaxKey(); // 返回 "hello"
allOne.getMinKey(); // 返回 "hello"
allOne.inc("leet");
allOne.getMaxKey(); // 返回 "hello"
allOne.getMinKey(); // 返回 "leet"
 

提示:
1 <= key.length <= 10
key 由小写英文字母组成
测试用例保证:在每次调用 dec 时,数据结构中总存在 key
最多调用 inc、dec、getMaxKey 和 getMinKey 方法 5 * 10^4 次

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/all-oone-data-structure
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题分析

        显而易见应该用哈希表(python dict)来进行存储和维护。

        关键是要实现对所有操作的的复杂度。所以,maxKey和minKey的维护不能集中在查询发生时才去搜索查询,而是因为在每次inc,dec命令执行时相应以incremental方式更新maxKey和minKey(当然与之相伴的还有minValue和maxValue)。

        但是每次inc,dec命令执行时Incremental方式更新有很多坑!这也就是为什么这道看上去概念非常简单、人畜无害的题目被标为difficult的原因了。

        以下分别讨论(分类讨论的要点在于如何把所有情况分割为完备而无重叠的一个partition)。在以下讨论用决策树的形式表达分类情况。

2.1 inc()时的更新

2.2 dec()时的更新

3. 代码实现
class AllOne:
    
    def __init__(self):
        self.strCnt   = dict()
        self.maxValue = 0
        self.minValue = float('inf')
        self.maxKey   = ''
        self.minKey   = ''

    def searchMinKey(self):
        self.minValue = float('inf')
        self.minKey   = ''
        for key in self.strCnt:
            if self.minValue > self.strCnt[key]:
                self.minValue = self.strCnt[key]
                self.minKey = key                        

    def searchMaxKey(self):
        self.maxValue = 0
        self.maxKey   = ''
        for key in self.strCnt:
            if self.maxValue < self.strCnt[key]:
                self.maxValue = self.strCnt[key]
                self.maxKey = key
        
    def inc(self, key: str) -> None:
        if key in self.strCnt:
            # Existing key increment.
            self.strCnt[key] = self.strCnt[key] + 1
            if len(self.strCnt) == 1:
                self.minValue = self.maxValue = self.strCnt[key]
                self.minKey   = self.maxKey   = key        
            else:
                # Incremental update of maxKey
                if self.maxValue < self.strCnt[key]:
                    self.maxValue = self.strCnt[key]
                    self.maxKey = key         

                # If this key is the original minKey, search for the new minKey                    
                if self.minKey == key:
                    self.searchMinKey()                                            
        else:
            # New key added.
            self.strCnt[key] = 1            
            # Always set the newly added item as the minKey
            self.minValue = 1
            self.minKey = key                                        
            
            if len(self.strCnt) == 1:
                self.maxValue = 1
                self.maxKey   = key        

    def dec(self, key: str) -> None:
        self.strCnt[key] = self.strCnt[key] - 1
        if self.strCnt[key] > 0:            
            if self.minValue > self.strCnt[key]:
                # Incremental update of minKey               
                self.minValue = self.strCnt[key]
                self.minKey = key                                       
            if key == self.maxKey:
                # If it is the original maxKey, search for the maxKey again
                self.searchMaxKey()                        
        else:
            # remove this key
            self.strCnt.pop(key)
        
            if len(self.strCnt)==0:
                self.maxValue = 0
                self.minValue = float('inf')
                self.maxKey   = ''
                self.minKey   = ''        
            else:
                if key == self.minKey:
                    self.searchMinKey()
                if key == self.maxKey:
                    self.searchMaxKey()
                                    
    def getMaxKey(self) -> str:
        return self.maxKey        

    def getMinKey(self) -> str:
        return self.minKey 

    def print(self):
        print('The details:',end='')
        print('minKey={0}, minValue={1}, maxKey={2}, maxValue={3}'.format(self.minKey, self.minValue, self.maxKey, self.maxValue))
        # for key in self.strCnt:
            # print(key, self.strCnt[key])
        print(self.strCnt)
if __name__ == '__main__':            
    
    print('testcase 1....')
    allOne = AllOne()
    cmd = ["AllOne", "inc", "inc", "getMaxKey", "getMinKey", "inc", "getMaxKey", "getMinKey"]
    para = [[], ["hello"], ["hello"], [], [], ["leet"], [], []]
    # expected output: [null, null, null, "hello", "hello", null, "hello", "leet"]
    for k in range(1,len(cmd)):
        print(cmd[k], para[k])
        if cmd[k] == 'inc':
            allOne.inc(para[k][0])
        elif cmd[k] == 'dec':
            allOne.dec(para[k][0])
        elif cmd[k] == 'getMaxKey':
            print(allOne.getMaxKey())
        elif cmd[k] == 'getMinKey':
            print(allOne.getMinKey())

        # allOne.print()    

        看上去人畜无害概念简单的一道题目,要追加运行效率而采取incremental更新方式,需要仔细分类考虑,覆盖各种corner case。。。扎扎实实地被虐了一把。

回到主目录:笨牛慢耕的Leetcode解题笔记(动态更新。。。)https://chenxiaoyuan.blog.csdn.net/article/details/123040889

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/767760.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号