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.

Solution: O(1) time complexity

解题思路主要参考了网友ivancjw的帖子,数据结构参考了https://discuss.leetcode.com/topic/65634/java-ac-all-strict-o-1-not-average-o-1-easy-to-read用bucket,思路是,我们建立一个次数分层的结构,次数多的在顶层,每一层放相同次数的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"}

 public class AllOne {
public class Bucket {
int count;
Bucket prev;
Bucket next;
HashSet<String> keySet;
public Bucket(int num) {
this.count = num;
this.keySet = new HashSet<String>();
}
} Bucket head;
Bucket tail;
HashMap<String, Integer> keyCountMap;
HashMap<Integer, Bucket> countBucketMap; /** Initialize your data structure here. */
public AllOne() {
this.head = new Bucket(Integer.MIN_VALUE);
this.tail = new Bucket(Integer.MAX_VALUE);
head.next = tail;
tail.prev = head;
this.keyCountMap = new HashMap<String, Integer>();
this.countBucketMap = new HashMap<Integer, Bucket>();
} /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
public void inc(String key) {
if (keyCountMap.containsKey(key)) {
change(key, 1);
}
else {
keyCountMap.put(key, 1);
if (head.next.count != 1) { //dont have the 1 bucket
addBucketAfter(new Bucket(1), head);
countBucketMap.put(1, head.next);
}
head.next.keySet.add(key);
}
} /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
public void dec(String key) {
if (keyCountMap.containsKey(key)) {
int count = keyCountMap.get(key);
if (count == 1) {
keyCountMap.remove(key);
removeKeyFromBucket(countBucketMap.get(count), key);
}
else change(key, -1);
}
} /** Returns one of the keys with maximal value. */
public String getMaxKey() {
return tail.prev==head? "" : (String)tail.prev.keySet.iterator().next();
} /** Returns one of the keys with Minimal value. */
public String getMinKey() {
return head.next==tail? "" : (String)head.next.keySet.iterator().next();
} public void change(String key, int offset) {
//get count, update keyCountMap
int count = keyCountMap.get(key);
keyCountMap.put(key, count+offset); //get current bucket
Bucket curBucket = countBucketMap.get(count); //new bucket
Bucket newBucket;
if (countBucketMap.containsKey(count+offset)) {
newBucket = countBucketMap.get(count+offset);
}
else {
newBucket = new Bucket(count+offset);
countBucketMap.put(count+offset, newBucket);
addBucketAfter(newBucket, (offset==1? curBucket : curBucket.prev));
}
newBucket.keySet.add(key);
removeKeyFromBucket(curBucket, key);
} public void removeKeyFromBucket(Bucket cur, String key) {
cur.keySet.remove(key);
if (cur.keySet.size() == 0) {
removeBucketFromList(cur);
countBucketMap.remove(cur.count);
}
} public void removeBucketFromList(Bucket cur) {
cur.prev.next = cur.next;
cur.next.prev = cur.prev;
cur.next = null;
cur.prev = null;
} public void addBucketAfter(Bucket bucket, Bucket preBucket) {
bucket.prev = preBucket;
bucket.next = preBucket.next;
preBucket.next.prev = bucket;
preBucket.next = bucket;
}
} /**
* 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();
*/

Solution 2: 如果不要求O(1)time, 这个用两个heap方法很常规

 public class AllOne {

     class Node{
String key;
int val;
public Node(String key, int val) {
this.key = key;
this.val = val;
}
}
/** Initialize your data structure here. */
HashMap<String, Node> map;
PriorityQueue<Node> minQ;
PriorityQueue<Node> maxQ;
public AllOne() {
map = new HashMap<String, Node>();
minQ = new PriorityQueue<Node>(new Comparator<Node>(){
public int compare(Node a, Node b) {
return a.val - b.val;
}
});
maxQ = new PriorityQueue<Node>(new Comparator<Node>(){
public int compare(Node a, Node b) {
return b.val - a.val;
}
});
} /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
public void inc(String key) {
if (!map.containsKey(key)) {
map.put(key, new Node(key, 1));
Node node = map.get(key);
minQ.add(node);
maxQ.add(node);
} else {
Node node = map.get(key);
minQ.remove(node);
maxQ.remove(node);
node.val++;
map.put(key, node);
minQ.add(node);
maxQ.add(node);
}
} /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
public void dec(String key) {
if (map.containsKey(key)) {
Node node = map.get(key);
if (node.val == 1) {
map.remove(key);
minQ.remove(node);
maxQ.remove(node);
} else {
minQ.remove(node);
maxQ.remove(node);
node.val--;
map.put(key, node);
minQ.add(node);
maxQ.add(node);
}
}
} /** Returns one of the keys with maximal value. */
public String getMaxKey() {
return maxQ.isEmpty() ? "" : maxQ.peek().key;
} /** Returns one of the keys with Minimal value. */
public String getMinKey() {
return minQ.isEmpty() ? "" : minQ.peek().key;
}
}

Leetcode: All O`one Data Structure的更多相关文章

  1. [LeetCode] 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] Add and Search Word - Data structure design 添加和查找单词-数据结构设计

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

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

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

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

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

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

  8. LeetCode 170. Two Sum III - Data structure design (两数之和之三 - 数据结构设计)$

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

  9. 【LeetCode】170. Two Sum III – Data structure design

    Difficulty:easy  More:[目录]LeetCode Java实现 Description Design and implement a TwoSum class. It should ...

随机推荐

  1. 【BZOJ】1086: [SCOI2005]王室联邦

    http://www.lydsy.com/JudgeOnline/problem.php?id=1086 题意:n个点的树,要求分块,使得每一块的大小在[b, 3b]内且块与某个点形成的块是连通的(某 ...

  2. GO语言练习:struct基础练习

    1.代码 2.运行 1.代码 package main import "fmt" type Rect struct { x, y float64 width, height flo ...

  3. 如何通过js和jquery获取图片真实的宽度和高度

    什么时候需要获取图片真实的宽度和高度 在做pc网页的时候,有时候会考虑按照插入的图片的尺寸来判断图片是横图还是竖图.然后判断过后给予不同的展示方式! 另外一种就是在手机页面上,在新闻页插入的图片往往都 ...

  4. 关于web前端(知乎上收集)

    1988年的图灵奖得主Ivan Sutherland就是搞人机交互的,事情跟现在的前端是一个路子. 微博上@_Franky: 这和司机一个道理. 开车也是易学难精的.基本个把月就能上路. 而需要赛车手 ...

  5. jQuery的常用事件

    1.$(document).ready() $(document).ready()是jQuery中响应JavaScript内置的onload事件并执行任务的一种典型方式.它和onload具有类似的效果 ...

  6. 使用explain查看mysql查询执行计划

    explain语句: 字段解释: type:     all(全表扫描)     ref() possible_keys:     预测使用什么列做为索引 key:     实际使用的key     ...

  7. House Robber

    You are a professional robber planning to rob houses along a street. Each house has a certain amount ...

  8. 获取客户端真实ip

    // 获取客户端真实ip() protected function getIP() { global $ip; if (getenv("HTTP_CLIENT_IP")) $ip ...

  9. shodan:黑客搜索引擎

    Shodan是msfconsole创始人与几个爱好技术的黑客开发的一款黑客搜索引擎,被称为可怕的搜索引擎,详细介绍见百度百科 网站地址:www.shodan.io 免费注册一账号,无账号的话,默认只显 ...

  10. HTTP协议 (二) 基本认证

    HTTP协议 (二) 基本认证 http协议是无状态的, 浏览器和web服务器之间可以通过cookie来身份识别. 桌面应用程序(比如新浪桌面客户端, skydrive客户端)跟Web服务器之间是如何 ...