几万年没做LeetCode的题了,更新一下。
https://leetcode.com/problems/all-oone-data-structure/description/
这道题的思路是用一个双向链表(list)来存储一个以value排序的数据结构,使用哈希表(unordered_map)来存储key到链表iterator的映射:
需要注意特殊处理value=1的Node的情况。
代码写得比较毛糙,但是确实是O(1)的复杂度,如果要优化的话map的插入可以用emplace()之类的。
注意:除了value=1的节点,其余节点的keys为空的时候要把该节点删除掉,否则getMaxKey()和getMinKey()就需要O(n)的遍历操作了。
struct KvNode { unordered_set<string> keys; int value = 1; }; class AllOne { private: list<KvNode> value_key; // arranged by val in ascending order using list_it_t = list<KvNode>::iterator; unordered_map<string, list_it_t> val_map; list_it_t init_node; //node with value one public: /** Initialize your data structure here. */ AllOne() { value_key.push_back(KvNode()); init_node = value_key.begin(); } /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */ void inc(const string& key) { if (val_map.find(key) == val_map.end()) { // `create' new node with value 1 init_node->keys.insert(key); val_map[key] = init_node; } else { // find existing node auto node_it = val_map[key]; node_it->keys.erase(key); //remove from current bulk auto next_it = std::next(node_it, 1); if (next_it == value_key.end() || next_it->value != node_it->value + 1) { // no valid valued bulk, create one KvNode node; node.keys.insert(key); node.value = node_it->value + 1; val_map[key] = value_key.insert(next_it, node); } else { next_it->keys.insert(key); val_map[key] = next_it; } if (node_it->keys.empty() && node_it->value != 1) { // remove node_it value_key.erase(node_it); } } } /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */ void dec(string key) { auto it_val_map = val_map.find(key); if (it_val_map == val_map.end()) { // key does not exist return; } else if (it_val_map->second->value == 1) { auto node_it = it_val_map->second; node_it->keys.erase(key); if (node_it->keys.empty() && node_it->value != 1) { value_key.erase(node_it); } val_map.erase(it_val_map); } else { auto node_it = it_val_map->second; auto prev_it = std::prev(node_it, 1); node_it->keys.erase(key); if (prev_it->value != node_it->value - 1) { // create one KvNode node; node.keys.insert(key); node.value = node_it->value - 1; val_map[key] = value_key.insert(node_it, node); } else { prev_it->keys.insert(key); val_map[key] = prev_it; } if (node_it->keys.empty() && node_it->value != 1) { value_key.erase(node_it); } } } /** Returns one of the keys with maximal value. */ string getMaxKey() { auto it_max = std::prev(value_key.end(), 1); if (!it_max->keys.empty()) return *(it_max->keys.begin()); else return ""; } /** Returns one of the keys with Minimal value. */ string getMinKey() { auto it_min = value_key.begin(); if (it_min->value == 1 && it_min->keys.empty()) ++it_min; if (it_min != value_key.end() && !it_min->keys.empty()) return *(it_min->keys.begin()); else return ""; } }; /** * 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(); */