LeetCode-432 全O(1)的数据结构
来源:力扣(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)的数据结构的更多相关文章
- Java实现 LeetCode 432 全 O(1) 的数据结构
432. 全 O(1) 的数据结构 实现一个数据结构支持以下操作: Inc(key) - 插入一个新的值为 1 的 key.或者使一个存在的 key 增加一,保证 key 不为空字符串. Dec(ke ...
- 【系统设计】432. 全 O(1) 的数据结构
题目: 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- 返回队列首部的元素. empty() -- 返回队列是 ...
- [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 ...
- [LeetCode] All O`one Data Structure 全O(1)的数据结构
Implement a data structure supporting the following operations: Inc(Key) - Inserts a new key with va ...
- LeetCode Binary Tree Postorder Traversal(数据结构)
题意: 用迭代法输出一棵二叉树的后序遍历结果. 思路: (1)用两个栈,一个存指针,一个存标记,表示该指针当前已经访问过哪些孩子了. /** * Definition for a binary tre ...
- LeetCode Implement Stack using Queues (数据结构)
题意: 用队列来实现栈. 思路: 没有什么捷径,纯粹模拟.但是用一个队列就够了. class Stack { /* // Push element x onto stack. void push(in ...
- LeetCode Implement Queue using Stacks (数据结构)
题意: 用栈来实现队列. 思路: 一个栈是不够的,至少要两个. (1)插入.永远只插入到stack1中(插到栈顶). (2)弹出.如果stack2不为空,直接弹出stack2的栈顶,否则,将stack ...
- C#LeetCode刷题-设计
设计篇 # 题名 刷题 通过率 难度 146 LRU缓存机制 33.1% 困难 155 最小栈 C#LeetCode刷题之#155-最小栈(Min Stack) 44.9% 简单 173 二叉搜索 ...
- leetcode难题
4 寻找两个有序数组的中位数 35.9% 困难 10 正则表达式匹配 24.6% 困难 23 合并K个排序链表 47.4% 困难 25 K ...
- Pandas_基础_全
Pandas基础(全) 引言 Pandas是基于Numpy的库,但功能更加强大,Numpy专注于数值型数据的操作,而Pandas对数值型,字符串型等多种格式的表格数据都有很好的支持. 关于Numpy的 ...
随机推荐
- 预编译SQL为什么能够防止SQL注入
前言 之前我一个搞网络安全的朋友问了我一个的问题,为啥用 PreparedStatement 预编译的 SQL 就不会有被 SQL 注入的风险? 第一时间我联想到的是八股文中关于 Mybatis 的脚 ...
- 【环境搭建】RocketMQ集群搭建
前置条件及效果图 条件: 两台服务器,个人是两台腾讯云服务器(其中嫖的朋友一个): 版本: rocketmq-version:4.4.0 rocketmq-console(mq控制台) Java:1. ...
- node设置下载源
// 设置镜像源 npm config set registry https://registry.npm.taobao.org // 查看当前源 npm config get registry
- Java基础篇——集合框架
集合--对象的容器 集合与数组相似,不同的是,集合的长度可变并且只能组合引用类型数据,如果要组合基本类型,则需要装箱成包装类 Collection体系集合 Collection父接口 Collecti ...
- P3845 [TJOI2007]球赛
简要题意 \(T\) 组数据,每一组数据给出 \(n\) 个数对 \((a,b)\).你需要将其分为几组,使得组单调不降.求最小组数. 思路 模拟赛考的题. 先来介绍 Dilworth 定理: 对于任 ...
- Windows 安装 Anaconda
下载 anaconda 官网 https://repo.anaconda.com/archive/ 国内镜像 https://mirrors.bfsu.edu.cn/anaconda/archive/ ...
- Ubuntu 22.04 安装 utools 时的疑难杂症
Error: libcrypto.so.1.1 原因:libcrypto.so.1.1 该依赖的版本不对,ubuntu 默认是使用的 openssl3 的依赖 这个是 openssl1 的 wget ...
- (19)go-micro微服务filebeat收集日志
目录 一 Filebeat介绍 二 FileBeat基本组成 三 FileBeat工作原理 四 Filebeat如何记录文件状态: 五 Filebeat如何保证事件至少被输出一次 六 安装Filebe ...
- 使用linux命令直接在网上下载文件,解压,改名
举例: 我们想要在服务器某个路径下,下载一个node.js包 操作如下 假如文件地址为https://npm.taobao.org/mirrors/node/v16.9.1/node-v16.9.1- ...
- Java入门与进阶 P-1.9+P-1.10
计算机的优先级 所有的数学运算都认为是从左向右运算的,Java 语言中大部分运算符也是从左向右结合的,只有单目运算符.赋值运算符和三目运算符例外,其中,单目运算符.赋值运算符和三目运算符是从右向左结合 ...