来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/all-oone-data-structure

题目描述

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

实现 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 * 104

解题思路

题目难点在于要将操作的时间复杂度全部变为O(1),对于修改来说,很容易想到哈希表,但是哈希表的查询最大值最小值的时间复杂度并不是O(1),查询最大值和最小值的时间复杂度为O(1)的很容易想到优先队列,但是优先队列的修改时间复杂度并不是O(1),所以,这里使用一个递增的双向链表来记录所有数据,当查询最小值返回链表头,查询最大值返回链表尾,并且通过哈希表将链表结点和key值绑定,使得修改时候可以在O(1)时间内找到结点,结点内容存储的是一个set,这样可以将相同计数的结点合成一个结点,将修改的过程缩短到O(1)的时间复杂度。注意在修改时候,分类处理未出现过的key和已出现的key,还有计数为0的key。

代码展示

class AllOne {
public:
list<pair<unordered_set<string>, int>> NodeList;
unordered_map<string, list<pair<unordered_set<string>, int>>::iterator> mapstriterMap;
AllOne() { } void inc(string key) {
if(mapstriterMap.count(key))
{
auto curIter = mapstriterMap[key];
auto nextIter = next(curIter);
if(nextIter == NodeList.end() || curIter->second + 1 < nextIter->second)
{
unordered_set<string> node{key};
mapstriterMap[key] = NodeList.emplace(nextIter, node, curIter->second + 1);
}
else
{
nextIter->first.emplace(key);
mapstriterMap[key] = nextIter;
}
curIter->first.erase(key);
if(curIter->first.empty())
NodeList.erase(curIter);
}
else
{
if(NodeList.empty() || NodeList.begin()->second != 1)
{
unordered_set<string> node{key};
NodeList.emplace_front(node, 1);
}
else
{
NodeList.begin()->first.emplace(key);
}
mapstriterMap[key] = NodeList.begin();
}
} void dec(string key) {
if(mapstriterMap.count(key))
{
auto curIter = mapstriterMap[key];
auto prevIter = prev(curIter);
if(curIter == NodeList.begin())
{
if(curIter->second - 1 <= 0)
{
mapstriterMap.erase(key);
}
else
{
unordered_set<string> node{key};
NodeList.emplace_front(node, curIter->second - 1);
mapstriterMap[key] = NodeList.begin();
}
}
else if(curIter->second - 1 > prevIter->second)
{
unordered_set<string> node{key};
mapstriterMap[key] = NodeList.emplace(curIter, node, curIter->second - 1);
}
else
{
prevIter->first.emplace(key);
mapstriterMap[key] = prevIter;
}
curIter->first.erase(key);
if(curIter->first.empty())
NodeList.erase(curIter);
}
} string getMaxKey() {
return NodeList.empty()? "" : *NodeList.rbegin()->first.begin();
} string getMinKey() {
return NodeList.empty()? "" : *NodeList.begin()->first.begin();
}
}; /**
* Your AllOne object will be instantiated and called as such:
* AllOne* obj = new AllOne();
* obj->inc(key);
* obj->dec(key);
* string param_3 = obj->getMaxKey();
* string param_4 = obj->getMinKey();
*/

运行结果

LeetCode-432 全O(1)的数据结构的更多相关文章

  1. Java实现 LeetCode 432 全 O(1) 的数据结构

    432. 全 O(1) 的数据结构 实现一个数据结构支持以下操作: Inc(key) - 插入一个新的值为 1 的 key.或者使一个存在的 key 增加一,保证 key 不为空字符串. Dec(ke ...

  2. 【系统设计】432. 全 O(1) 的数据结构

    题目: 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- 返回队列首部的元素. empty() -- 返回队列是 ...

  3. [leetcode]432. All O`one Data Structure全O(1)数据结构

    Implement a data structure supporting the following operations: Inc(Key) - Inserts a new key with va ...

  4. [LeetCode] All O`one Data Structure 全O(1)的数据结构

    Implement a data structure supporting the following operations: Inc(Key) - Inserts a new key with va ...

  5. LeetCode Binary Tree Postorder Traversal(数据结构)

    题意: 用迭代法输出一棵二叉树的后序遍历结果. 思路: (1)用两个栈,一个存指针,一个存标记,表示该指针当前已经访问过哪些孩子了. /** * Definition for a binary tre ...

  6. LeetCode Implement Stack using Queues (数据结构)

    题意: 用队列来实现栈. 思路: 没有什么捷径,纯粹模拟.但是用一个队列就够了. class Stack { /* // Push element x onto stack. void push(in ...

  7. LeetCode Implement Queue using Stacks (数据结构)

    题意: 用栈来实现队列. 思路: 一个栈是不够的,至少要两个. (1)插入.永远只插入到stack1中(插到栈顶). (2)弹出.如果stack2不为空,直接弹出stack2的栈顶,否则,将stack ...

  8. C#LeetCode刷题-设计

    设计篇 # 题名 刷题 通过率 难度 146 LRU缓存机制   33.1% 困难 155 最小栈 C#LeetCode刷题之#155-最小栈(Min Stack) 44.9% 简单 173 二叉搜索 ...

  9. leetcode难题

    4 寻找两个有序数组的中位数       35.9% 困难     10 正则表达式匹配       24.6% 困难     23 合并K个排序链表       47.4% 困难     25 K ...

  10. Pandas_基础_全

    Pandas基础(全) 引言 Pandas是基于Numpy的库,但功能更加强大,Numpy专注于数值型数据的操作,而Pandas对数值型,字符串型等多种格式的表格数据都有很好的支持. 关于Numpy的 ...

随机推荐

  1. Jvm上如何运行其他语言?JSR223规范最详细讲解

    一 在Java的平台里,其实是可以执行其他的语言的.包括且不仅限于jvm发展出来的语言. 有的同学可能会说,在java项目里执行其他语言,这不吃饱了撑着么,java体系那么庞大,各种工具一应俱全,放着 ...

  2. GO语言基础 为什么我要学习Golang以及GO语言入门普及

    作为网络安全初学者,会遇到采用Go语言开发的恶意样本.因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识:另一方面是分享与读者,希望大家一起进步.这系列文章入门部分将参考 ...

  3. 或许是市面上最强的 Mock 工具

    背景 在开发过程中,由于后端与前端并行开发,或者前端需要等待后台开发,难以保证对接效率,同时即使用开发好的 API 对接,也有可能一个 API 不通就阻塞了整个软件的对接工作.同时对软件的敏感度也很高 ...

  4. GitHub - 电脑经常无法访问GitHub页面

    来自这里 1.打开Dns检测|Dns查询 - 站长工具2.在检测输入栏中输入http://github.com官网3.把检测列表里的TTL值最小的IP输入到host里,并对应写上github官网域名. ...

  5. CH32V307以太网(芯片内部10M)-针对新固件的Lib库

    沁恒的CH32V307网络库在前段时间做了一个更新,相对于以前的Lib,主要的功能没有什么特别大的变化,但是底层的一些操作仔细看的话,还是不少的区别的. 首先,官方提供的例程,工程结构以及头文件优一些 ...

  6. 一步步教你在Edge浏览器上安装网风笔记

    微软于2022年6月15日正式结束对浏览器"Internet Explorer (IE)"的支持,IE已正式退出历史舞台,取而代之的是目前风头正盛的被微软称为当今最好用的Edge浏 ...

  7. Hadoop详解(05) – MapReduce

    Hadoop详解(05) – MapReduce MapReduce概述 定义 MapReduce是一个分布式运算程序的编程框架,是用户 "基于Hadoop的数据分析应用" 开发的 ...

  8. 图解 Andrew 算法求凸包

    前言 Andrew 算法可以在 \(O(n\log n)\) 的时间复杂度通过单调栈分别求出散点的上凸壳和下凸壳,来求出平面上一些点的凸包. 看懂这篇博客,大家需要掌握: 基础计算几何知识 单调栈 凸 ...

  9. java入门与进阶 P-3.2+P-3.3+P3.4

    数数字 例如:Scanner sc = new Scanner(System.in);int number = sc.nextInt();int count= 0;while(number>0) ...

  10. python加密解密之AES

    def encrypt(self, params: str, key: str, iv: str) -> str: """加密""" ...