[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 ...
随机推荐
- Linux 解决数量庞大wildfly容器启动与停止的脚本
一.问题 因公司业务的发展,后台架构的变更,导致测试环境(Linux)部署与管理困难成倍增长,duang的一下,增加N倍.进入正题说问题: 问题1. 测试环境包含普通用户环境.开发者用户环境,原来只 ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
- VS2015突然报错————Encountered an unexpected error when attempting to resolve tag helper directive '@addTagHelper' with value 'Microsoft.AspNet.Mvc.Razor.TagHelpers.UrlResolutionTagHelper
Encountered an unexpected error when attempting to resolve tag helper directive '@addTagHelper' with ...
- 04实现累加和计算功能并且实现textbox不允许输入数字以外的字符但不包括退格键同时不允许第一个数值为0
private void button1_Click(object sender, EventArgs e) { double number1, number2; if (double.TryPars ...
- iOS学习笔记——滚动视图(scrollView)
滚动视图:在根视图中添加UIScrollViewDelegate协议,声明一些对象属性 @interface BoViewController : UIViewController<UIScro ...
- 偷天换日:网络劫持,网页js被伪装替换。
偷天换日 3月12号石家庄一个客户(后面简称乙方)有几家门店,平台收银(web)有一些功能无法正常使用,平台有上千家门店在使用,到目前为止别的省份都没有此问题.远程协助发现,js日期控件无法正常调用, ...
- android ImageView网络图片加载、动态设置尺寸、圆角..
封装了一个关于ImageView的辅助类,该类可以方便实现网络图片下载的同时,动态设置图片尺寸.圆角.....一系列连贯的操作,无样式表,java代码实现所有功能,使用很方便. package com ...
- 【微信开发】公众号后台设置错误导致的微信redirect_uri参数错误【图】
在微信开发中,如微信网页授权登录,分享到朋友圈自定义内容,微信h5支付时 可能会遇到微信redirect_uri参数错误的情况. 此时除了检查自己代码正确性外,还要检查一下是否正确地设置了公众号后台的 ...
- 四种解析和创建方式(DOM,SAX,DOM4J,JDOM)
一.先导入jar包 DOM基于树形,SAX基于事件,DOM4J和JDOM基于底层API 二.代码如下 1 package com.sxt.test; import java.io.File; impo ...
- chunkupload文件上传断点续传组件(java)
chunkupload简介 chunkupload是一款基于java语言的断点续传组件,针对文件上传,非文件下载,集成方便,使用简单. 从整体上讲,chunkupload会对文件进行切片处理,每个切片 ...