思路:
1、时间复杂度要求O(1),由key查询value操作必须用 hash table
2、getMax, getMin 操作要实现O(1)的复杂度,必须要用有序的 list/vector
3、inc, dec操作要实现O(1)的复杂度,必须要用有序的 list
实现方法:
hash table:key为string,映射为list的迭代器
list:每一个节点内容:value + {keys} (即,节点的int值,和指向该节点的key值的集合)
特点:
用到了C++ STL中的unordered_map, unordered_set, list多种容器和对应的操作, 对应的迭代器的操作。
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) {
auto it = m.find(key); //查找key对应的链表中的节点的迭代器构成的:映射对
if(it == m.end()){ //如果key不在map m中 //bug1:查找key是否在map m中,应该与m.end()比较,而不是l.end()
if(l.empty() || l.front().val != 1){ //链表中没有节点,或者头节点的val值不为1
l.push_front({1, {key}});
}
else{ //链表头节点的val值为1
l.front().keys.insert(key); //bug2:l头节点的keys,少打了front()
}
m[key] = l.begin(); //让新的key映射到链表l的头节点的迭代器
return; //bug3: 忘记了return,造成执行时出错 runtime error: member access within null pointer of type 'struct __node_type' (hashtable_policy.h)
}
auto lit = it->second; //得到hash对的value, 即list的迭代器
auto nextlit = next(lit); //如果key对应链表中的某个节点的迭代器,取它的下一个节点的迭代器
if(nextlit==l.end() || nextlit->val != (lit->val + 1)){
nextlit = l.insert(nextlit, {lit->val+1, {}});//要插在原来lit的节点的下一个节点,所以insert第一个参数是nextlit.插入节点的迭代器返回给nextlit,也可以省略不写
}
nextlit -> keys.insert(key);
m[key] = nextlit;
//清除原来节点的key,m中的key的映射此时已经更新,不用再改
lit->keys.erase(key);
if(lit->keys.empty())
l.erase(lit); //如果这个节点已经没有key映射到,在链表中清除该节点
}
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
void dec(string key) {
auto it = m.find(key);
if(it == m.end()) return; //找不到key对应的节点,无法执行val减一操作,直接返回
auto lit = it->second;
auto prelit = prev(lit);
if(lit->val > 1){
if(lit == l.begin() || (lit->val-1 != prelit->val)){
prelit = l.insert(lit, {lit->val-1, {}}); // bug 4:插入位置错误.,在prelit之后、lit之前插入.insert()插入的元素会出现在lit之前
}
prelit->keys.insert(key);
m[key] = prelit;
}
else{
// 如果val == 1
m.erase(key);
//lit->keys.erase(key);
//if(lit->keys.empty())
// l.erase(lit);
}
lit->keys.erase(key);
if(lit->keys.empty())
l.erase(lit);
}
/** Returns one of the keys with maximal value. */
string getMaxKey() {
return l.empty()? "" : *l.back().keys.cbegin();
}
/** Returns one of the keys with Minimal value. */
string getMinKey() {
return l.empty()? "" : *l.front().keys.cbegin();
}
private:
struct Node {
int val;
unordered_set<string> keys; //该节点中val对应的key的集合,也就是指向该节点的key的集合
};
list<Node> l;
//unordered_map<string, Node> m;
unordered_map<string, list<Node>::iterator> m; //哈希表的key映射为链表中的某个节点的迭代器,以实现O(1)时间访问链表中某节点
};
/**
* 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();
*/