Implement a data structure supporting the following operations:

  1. 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.
  2. 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.
  3. GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string "".
  4. 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;
};

类似题目:

LRU Cache

参考资料:

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)的数据结构的更多相关文章

  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 ...

  2. [LeetCode] Two Sum III - Data structure design 两数之和之三 - 数据结构设计

    Design and implement a TwoSum class. It should support the following operations:add and find. add - ...

  3. LeetCode Two Sum III - Data structure design

    原题链接在这里:https://leetcode.com/problems/two-sum-iii-data-structure-design/ 题目: Design and implement a ...

  4. Leetcode: All O`one Data Structure

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

  5. 【LeetCode】211. Add and Search Word - Data structure design 添加与搜索单词 - 数据结构设计

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:Leetcode, 力扣,211,搜索单词,前缀树,字典树 ...

  6. [LeetCode] Add and Search Word - Data structure design 添加和查找单词-数据结构设计

    Design a data structure that supports the following two operations: void addWord(word) bool search(w ...

  7. 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 ...

  8. leetcode@ [211] Add and Search Word - Data structure design

    https://leetcode.com/problems/add-and-search-word-data-structure-design/ 本题是在Trie树进行dfs+backtracking ...

  9. leetcode面试准备:Add and Search Word - Data structure design

    leetcode面试准备:Add and Search Word - Data structure design 1 题目 Design a data structure that supports ...

随机推荐

  1. CloudNotes之领域建模篇:领域模型简介

    CloudNotes领域模型还是相对简单的,并不一定需要采用面向领域驱动的设计方法来解决CloudNotes的领域问题.但出于以下几个方面的原因,我还是采用了面向领域驱动的方式来开发CloudNote ...

  2. 实践 HTML5 的 CSS3 Media Queries

    先来介绍下 media,确切的说应该是 CSS media queries(CSS 媒体查询),媒体查询包含了一个媒体类型和至少一个使用如宽度.高度和颜色等媒体属性来限制样式表范围的表达式.CSS3 ...

  3. C# 文件下载之断点续传

    注意,本文所说的断点续传特指 HTTP 协议中的断点续传.本文主要聊聊思路和关键代码,更多细节请参考本文附带的 demo. 工作原理 HTTP 协议中定义了一些请求/响应头,通过组合使用这些头信息.我 ...

  4. [Winform] DataGridView 总结(FAQ)

    Q1.  如何使单元格不可编辑? A:设置 ReadOnly 属性,可以设置的对象包括 DataGridViewRow(行).DataGridViewColumn(列).DataGridViewCel ...

  5. hibernate.cfg.xml

    <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN&q ...

  6. Java微信公众平台接口封装源码分享

    前言:      这篇博客是在三月初动手项目的时候准备写的,但是为了完成项目只好拖延时间写这篇博客,顺便也可以在项目中应用我自己总结的的一些经验.今天看来,这些方法的应用还是可以的,至少实现了我之前的 ...

  7. opts=opts | |{}

    var opts=opts || {}这个语句是一个赋值或者初始化语句 该语句在opts已经被初始化过后opts的值不变,即执行var opts=opts这一部分. 当opts未被初始化,即typeo ...

  8. windows上如何搭建Git Server

    Git在版本控制方面,相比与SVN有更多的灵活性,对于开源的项目,我们可以托管到Github上面,非常方便,但是闭源的项目就会收取昂贵的费用.那么私有项目,如何用Git进行代码版本控制呢?我们可以自己 ...

  9. JS高程5.引用类型(4)Array类型的各类方法

    一.转换方法 所有的对象都具有toLocaleString(),toString()和valueOf()方法.调用toString()方法会返回由数组中的每个值的字符串拼接而成的一个以逗号分隔的字符串 ...

  10. JQuery效果-淡入淡出、滑动、动画

    一.JQuery Fading方法 JQuery 有四种fade方法 1.fadeIn() 淡入                       对应也有$(selector).fadeIn(speed, ...