见到O(1),肯定是用哈希表了
但是取最大最小值的过程不是O(1),所以最好是在插入的过程中就能保持顺序
方法是维护一个矩阵,行是键的值,列是键(string)
(first)row0: val = 4, strs = {"A", "B"}
row1: val = 3, strs = {"D"}
(last)row2: val = 2, strs = {"C"}
inc过程:
if the key isn't in the matrix:
if the matrix is empty or the value of the last row isn't 1:
insert a new row with value 1 to the end of the matrix, and put the key in the new row;
else:
put the key in the last row of the matrix;
else:
if the key is at the first row or last_row.value != current_row.value + 1:
insert a new row before current row, with value current_row.value + 1, and move the key to the new row;
else:
move the key from current row to last row;
代码:
struct Bucket { int val; unordered_set<string> keys; };
list<Bucket> buckets;
unordered_map<string, list<Bucket>::iterator> m;
这三行定义完全定义了行号和键值(string)的映射关系,其中Bucket中的unordered_set进一步把查询的时间复杂度降到了O(1)
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 != 1) {
auto newBucket = buckets.insert(buckets.end(), { 1,{ 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 + 1) {
auto newBucket = buckets.insert(curBucket, { curBucket->val + 1,{ 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 == 1) {
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 - 1) {
auto newBucket = buckets.insert(nextBucket, { curBucket->val - 1,{ 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;
};