[LeetCode] All O`one Data Structure 全O(1)的数据结构
Implement a data structure supporting the following operations:
- Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty string.
- Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string.
- GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string
"". - GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string
"".
Challenge: Perform all these in O(1) time complexity.
这道题让我们实现一个全是O(1)复杂度的数据结构,包括了增加key,减少key,获取最大key,获取最小key,这几个函数。由于需要常数级的时间复杂度,我们首先第一反应就是要用哈希表来做,不仅如此,我们肯定还需要用list来保存所有的key,那么哈希表就是建立key和list中位置迭代器之间的映射,这不由得令人想到了之前那道LRU Cache,也是用了类似的方法来解,但是感觉此题还要更加复杂一些。由于每个key还要对应一个次数,所以list中不能只放key,而且相同的次数可能会对应多个key值,所以我们用unordered_set来保存次数相同的所有key值,我们建立一个Bucket的结构体来保存次数val,和保存key值的集合keys。解题思路主要参考了网友ivancjw的帖子,数据结构参考了史蒂芬大神的帖子,思路是,我们建立一个次数分层的结构,次数多的在顶层,每一层放相同次数的key值,例如下面这个例子:
"A": 4, "B": 4, "C": 2, "D": 1
那么用我们设计的结构保存出来就是:
row0: val = 4, keys = {"A", "B"}
row1: val = 2, keys = {"C"}
row2: val = 1, keys = {"D"}
好,我们现在来分析如何实现inc函数,我们来想,如果我们插入一个新的key,跟我们插入一个已经存在的key,情况是完全不一样的,那么我们就需要分情况来讨论:
- 如果我们插入一个新的key,那么由于该key没有出现过,所以加入后次数一定为1,那么就有两种情况了,如果list中没有val为1的这一行,那么我们需要插入该行,如果已经有了val为1的这行,我们直接将key加入集合keys中即可。
- 如果我们插入了一个已存在的key,那么由于个数增加了1个,所以该key值肯定不能在当前行继续待下去了,要往上升职啊,那么这里就有两种情况了,如果该key要升职到的那行不存在,我们需要手动添加那一行;如果那一行存在,我们之间将key加入集合keys中,记得都要将原来行中的key值删掉。
下面我们再来看dec函数如何实现,其实理解了上面的inc函数,那么dec函数也就没什么难度了:
- 如果我们要删除的key不存在,那么直接返回即可。
- 如果我们要删除的key存在,那么我们看其val值是否为1,如果为1的话,那么直接在keys中删除该key即可,然后还需要判断如果该key是集合中的唯一一个,那么该行也需要删除。如果key的次数val不为1的话,我们要考虑降级问题,跟之前的升职很类似,如果要降级的行不存在,我们手动添加上,如果存在,则直接将key值添加到keys集合中即可。
当我们搞懂了inc和dec的实现方法,那么getMaxKey()和getMinKey()简直就是福利啊,不要太简单啊,直接返回首层和尾层的key值即可,参见代码如下:
class AllOne {
public:
/** Initialize your data structure here. */
AllOne() {}
/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
void inc(string key) {
if (!m.count(key)) {
if (buckets.empty() || buckets.back().val != ) {
auto newBucket = buckets.insert(buckets.end(), {, {key}});
m[key] = newBucket;
} else {
auto newBucket = --buckets.end();
newBucket->keys.insert(key);
m[key] = newBucket;
}
} else {
auto curBucket = m[key], lastBucket = (--m[key]);
if (lastBucket == buckets.end() || lastBucket->val != curBucket->val + ) {
auto newBucket = buckets.insert(curBucket, {curBucket->val + , {key}});
m[key] = newBucket;
} else {
lastBucket->keys.insert(key);
m[key] = lastBucket;
}
curBucket->keys.erase(key);
if (curBucket->keys.empty()) buckets.erase(curBucket);
}
}
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
void dec(string key) {
if (!m.count(key)) return;
auto curBucket = m[key];
if (curBucket->val == ) {
curBucket->keys.erase(key);
if (curBucket->keys.empty()) buckets.erase(curBucket);
m.erase(key);
return;
}
auto nextBucket = ++m[key];
if (nextBucket == buckets.end() || nextBucket->val != curBucket->val - ) {
auto newBucket = buckets.insert(nextBucket, {curBucket->val - , {key}});
m[key] = newBucket;
} else {
nextBucket->keys.insert(key);
m[key] = nextBucket;
}
curBucket->keys.erase(key);
if (curBucket->keys.empty()) buckets.erase(curBucket);
}
/** Returns one of the keys with maximal value. */
string getMaxKey() {
return buckets.empty() ? "" : *(buckets.begin()->keys.begin());
}
/** Returns one of the keys with Minimal value. */
string getMinKey() {
return buckets.empty() ? "" : *(buckets.rbegin()->keys.begin());
}
private:
struct Bucket { int val; unordered_set<string> keys; };
list<Bucket> buckets;
unordered_map<string, list<Bucket>::iterator> m;
};
类似题目:
参考资料:
https://discuss.leetcode.com/topic/63827/c-solution-with-comments
https://discuss.leetcode.com/topic/63683/0ms-all-in-o-1-with-detailed-explantation
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] All O`one Data Structure 全O(1)的数据结构的更多相关文章
- [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] Two Sum III - Data structure design 两数之和之三 - 数据结构设计
Design and implement a TwoSum class. It should support the following operations:add and find. add - ...
- LeetCode Two Sum III - Data structure design
原题链接在这里:https://leetcode.com/problems/two-sum-iii-data-structure-design/ 题目: Design and implement a ...
- Leetcode: All O`one Data Structure
Implement a data structure supporting the following operations: Inc(Key) - Inserts a new key with va ...
- 【LeetCode】211. Add and Search Word - Data structure design 添加与搜索单词 - 数据结构设计
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:Leetcode, 力扣,211,搜索单词,前缀树,字典树 ...
- [LeetCode] Add and Search Word - Data structure design 添加和查找单词-数据结构设计
Design a data structure that supports the following two operations: void addWord(word) bool search(w ...
- Java for LeetCode 211 Add and Search Word - Data structure design
Design a data structure that supports the following two operations: void addWord(word)bool search(wo ...
- leetcode@ [211] Add and Search Word - Data structure design
https://leetcode.com/problems/add-and-search-word-data-structure-design/ 本题是在Trie树进行dfs+backtracking ...
- leetcode面试准备:Add and Search Word - Data structure design
leetcode面试准备:Add and Search Word - Data structure design 1 题目 Design a data structure that supports ...
随机推荐
- 巡检脚本OS+Oracle
巡检脚本 主机巡检脚本:OSWatcher.sh Oracle巡检脚本:ORAWatcher.sh 脚本使用方法 1.建立脚本放置目录 # mkdir /var/collect 2.把脚本ORAWat ...
- unity3d 免费好用的数据库处理框架 数据库直连框架
一.概述 前不久有一个哥们做PC游戏开发的.使用到Unity3d, 正好找到我. 我给他提供了Unity3d如何Moon.Orm来智能化编程的方式. 我们先看看怎么更加便捷sqlite. http:/ ...
- DataTable与DTO对象的简易转换类
在web开发过程中,有时候为了数据传输的方便,比如:后台需要更新前端的ViewModel,此时我们定义一个与前端ViewModel结构一样的DTO对象,从数据层获取数据后,将数据封装成DTO然后序列化 ...
- iOS UITableViewableViewCell自适应高度
前两天做了一个项目,中间有遇到一个问题,就是聊天的时候cell高度的问题.这是一个很多前辈都遇到过,并且很完美的解决过的问题.这里主要是记录自己的学习心得.项目中首先想到的是用三方库,可是有问题,遂放 ...
- 前端开发:css技巧,如何设置select、radio 、 checkbox 、file这些不可直接设置的样式 。
前言: 都说程序员有三宝:人傻,钱多,死得早.博主身边的程序“猿”一大半应了这三宝,这从侧面说明了一个问题,只有理性是过不好日子的.朋友们应该把工作与生活分开,让生活变得感性,让工作变得理性,两者相提 ...
- asp.net mvc 上传文件
转至:http://www.cnblogs.com/fonour/p/ajaxFileUpload.html 0.下载 http://files.cnblogs.com/files/fonour/aj ...
- ListFragment的使用
ListFragment继承了Fragment,顾名思义,ListFragment是一种特殊的Fragment,它包含了一个ListView,在ListView里面显示数据. 1. MainActiv ...
- FunDA(1)- Query Result Row:强类型Query结果行
FunDA的特点之一是以数据流方式提供逐行数据操作支持.这项功能解决了FRM如Slick数据操作以SQL批次模式为主所产生的问题.为了实现安全高效的数据行操作,我们必须把FRM产生的Query结果集转 ...
- Redis主从复制
大家可以先看这篇文章ASP.NET Redis 开发对Redis有个初步的了解 Redis的主从复制功能非常强大,一个master可以拥有多个slave,而一个slave又可以拥有多个slave,如此 ...
- app端上传文件至服务器后台,web端上传文件存储到服务器
1.android前端发送服务器请求 在spring-mvc.xml 将过滤屏蔽(如果不屏蔽 ,文件流为空) <!-- <bean id="multipartResolver&q ...