[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 ...
随机推荐
- 【分布式】Zookeeper系统模型
一.前言 前面已经讲解了Zookeeper的一些应用场景,但是并没有深入到Zookeeper内部进行分析,本篇将讲解其系统模型. 二.系统模型 2.1 数据模型 Zookeeper的数据节点称为ZNo ...
- PHP之提取多维数组指定列的方法
前言:有时候在开发中会遇到这样的问题,我们需要把有规律的多维数组按照纵向(列)取出,有下面的方法可用: 我们将拿下面的数组来处理: $arr = array( '0' => array('id' ...
- Scrapy:为spider指定pipeline
当一个Scrapy项目中有多个spider去爬取多个网站时,往往需要多个pipeline,这时就需要为每个spider指定其对应的pipeline. [通过程序来运行spider],可以通过修改配置s ...
- 怎样写一个webpack loader
div{display:table-cell;vertical-align:middle}#crayon-theme-info .content *{float:left}#crayon-theme- ...
- Shell脚本编程30分钟入门
Shell脚本编程30分钟入门 转载地址: Shell脚本编程30分钟入门 什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd ~ mkdir shell_tut cd shell_t ...
- Socket初识
基础概念 Socket,套接字,本质是网络编程接口.提供网络通信的能力,实现不同虚拟机或不同计算机之间的通信.面向客户/服务(C/S)模型,socket是应用层和传输层之间的中间软件抽象层: 顶上三层 ...
- python 数据类型 ---字符串
1. 字符串去除空白 ,strip() , 包括空格,tab键, 换行符 >>> name = " Frank " >>> name.strip ...
- Python3.5安装及opencv安装
Python安装注意事项(版本3.5,系统windows)1.安装好Python后将D:\Program Files\Python.D:\Program Files\Python\Scripts加入P ...
- AngularJS下对数组的比较
Javascript不能直接用==或者===来判断两个数组是否相等,无论是相等还是全等都不行,以下两行JS代码都会返回false <script type="text/javascri ...
- GridView的各种属性
<GridView android:id="@+id/movie_list" android:layout_width="906dp" android:l ...