Design
// LRU Cache
// 99 ms
class LRUCache {
private:
int capacity;
int size;
unordered_map cache;
unordered_map::iterator> position;
list visited;
public:
LRUCache(int capacity) {
this->capacity = capacity;
this->size = 0;
}
int get(int key) {
if (cache.find(key) != cache.end()) {
visit(key);
return cache[key];
}
return -1;
}
void put(int key, int value) {
if (cache.find(key) != cache.end()) {
cache[key] = value;
visit(key);
} else {
if (size == capacity)
invalidate();
cache[key] = value;
visited.push_front(key);
position[key] = visited.begin();
size++;
}
}
void visit(int key) {
list::iterator iter = position[key];
visited.erase(iter);
visited.push_front(key);
position[key] = visited.begin();
}
void invalidate() {
int key = visited.back();
visited.pop_back();
cache.erase(key);
position.erase(key);
size--;
}
};
// 86 ms
class LRUCache {
private:
struct CacheNode {
int key;
int value;
CacheNode(int k, int v) : key(k), value(v) {}
};
public:
LRUCache(int capacity) {
this->capacity = capacity;
}
int get(int key) {
if (cacheMap.find(key) != cacheMap.end()) {
cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
cacheMap[key] = cacheList.begin();
return cacheMap[key]->value;
} else {
return -1;
}
}
void put(int key, int value) {
if (capacity == 0)
return;
if (cacheMap.find(key) != cacheMap.end()) {
cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
cacheMap[key] = cacheList.begin();
cacheMap[key]->value = value;
} else {
if (cacheMap.size() == capacity) {
cacheMap.erase(cacheList.back().key);
cacheList.pop_back();
}
cacheList.emplace_front(CacheNode(key, value)); // emplace_front比push_front快
cacheMap[key] = cacheList.begin();
}
}
private:
int capacity;
list cacheList;
unordered_map::iterator> cacheMap;
};
// LFU Cache
// 99ms
class LFUCache {
private:
struct FrequencyListNode {
int frequency;
list visited;
FrequencyListNode(int f) : frequency(f) {}
};
int capacity;
int size;
unordered_map cache;
list frequencyList;
unordered_map::iterator> index1;
unordered_map::iterator> index2;
public:
LFUCache(int capacity) {
this->capacity = capacity;
this->size = 0;
}
int get(int key) {
if (cache.find(key) != cache.end()) {
visit(key);
return cache[key];
}
return -1;
}
void put(int key, int value) {
if (capacity == 0)
return;
if (cache.find(key) != cache.end()) {
cache[key] = value;
visit(key);
} else {
if (size == capacity)
invalidate();
cache[key] = value;
if (frequencyList.empty() || (frequencyList.front()).frequency > 1)
frequencyList.push_front(FrequencyListNode(1));
(frequencyList.front()).visited.push_front(key);
index1[key] = frequencyList.begin();
index2[key] = (frequencyList.begin())->visited.begin();
size++;
}
}
void visit(int key) {
list::iterator iter1 = index1[key];
list::iterator iter2 = index2[key];
int frequency = iter1->frequency;
iter1->visited.erase(iter2);
if (iter1->visited.empty())
iter1 = frequencyList.erase(iter1); // Important!: erase后重新赋给iter1
else
iter1++;
if (iter1 == frequencyList.end() || iter1->frequency > frequency + 1)
iter1 = frequencyList.insert(iter1, FrequencyListNode(frequency + 1)); // Important!: insert后重新赋给iter1
iter1->visited.push_front(key);
index1[key] = iter1;
index2[key] = iter1->visited.begin();
}
void invalidate() {
int key = (frequencyList.begin())->visited.back();
(frequencyList.begin())->visited.pop_back();
if ((frequencyList.begin())->visited.empty())
frequencyList.pop_front();
cache.erase(key);
index1.erase(key);
index2.erase(key);
size--;
}
};
// 168 ms
class LFUCache {
private:
struct CacheNode {
int key;
int value;
CacheNode(int k, int v) : key(k), value(v) {}
};
struct CacheBucket {
int frequency;
list cacheList;
unordered_map::iterator> cacheMap; // map (second-layer index)
CacheBucket(int f) : frequency(f) {}
};
public:
LFUCache(int capacity) {
this->capacity = capacity;
}
int get(int key) {
if (cacheMap.find(key) != cacheMap.end()) {
list::iterator bucket = cacheMap[key];
list::iterator node = bucket->cacheMap[key];
int value = node->value;
inc(bucket, key, value);
return value;
} else {
return -1;
}
}
void put(int key, int value) {
if (capacity == 0) return;
if (cacheMap.find(key) != cacheMap.end()) {
list::iterator bucket = cacheMap[key];
inc(bucket, key, value);
} else {
if (cacheMap.size() == capacity) {
cache.front().cacheMap.erase(cache.front().cacheList.back().key);
cacheMap.erase(cache.front().cacheList.back().key);
cache.front().cacheList.pop_back();
if (cache.front().cacheMap.empty())
cache.pop_front();
}
if (cache.empty() || cache.front().frequency > 1)
cache.insert(cache.begin(), CacheBucket(1));
cache.front().cacheList.push_front(CacheNode(key, value));
cache.front().cacheMap[key] = cache.front().cacheList.begin();
cacheMap[key] = cache.begin();
}
}
void inc(list::iterator &bucket, int key, int value) { // frequency + 1
int frequency = bucket->frequency;
bucket->cacheList.erase(bucket->cacheMap[key]);
bucket->cacheMap.erase(key);
if (bucket->cacheMap.empty())
bucket = cache.erase(bucket);
else
bucket++;
if (bucket == cache.end() || bucket->frequency > frequency + 1) {
cache.insert(bucket, CacheBucket(frequency + 1));
bucket--;
}
bucket->cacheList.push_front(CacheNode(key, value));
bucket->cacheMap[key] = bucket->cacheList.begin();
cacheMap[key] = bucket;
}
private:
int capacity;
list cache;
unordered_map::iterator> cacheMap; // map (first-layer index)
};
// Find Median from Data Stream
// 考虑两个优先队列(最大最小堆)
class MedianFinder {
public:
/** initialize your data structure here. */
MedianFinder() {}
void addNum(int num) {
if (maxpq.empty() || num <= maxpq.top()) {
maxpq.push(num);
if (maxpq.size() > minpq.size() + 1) {
int median = maxpq.top();
maxpq.pop();
minpq.push(median);
}
} else {
minpq.push(num);
if (maxpq.size() < minpq.size()) {
int median = minpq.top();
minpq.pop();
maxpq.push(median);
}
}
}
double findMedian() {
if (maxpq.size() == minpq.size())
return ((double)maxpq.top() + (double)minpq.top()) / 2;
else
return maxpq.top();
}
private:
priority_queue maxpq; // has smaller half of the numbers
priority_queue, greater> minpq; // has larger half of the numbers
// Ensure that maxpq.size() == minpq.size() or maxpq.size() == minpq.size() + 1
};
// Insert Delete GetRandom O(1)
class RandomizedSet {
public:
/** Initialize your data structure here. */
RandomizedSet() {
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val) {
if (pos.find(val) != pos.end())
return false;
elements.push_back(val);
pos[val] = elements.size() - 1;
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val) {
if (pos.find(val) == pos.end())
return false;
if (pos[val] < elements.size() - 1) {
int replace_val = elements.back();
pos[replace_val] = pos[val];
elements[pos[val]] = replace_val;
}
pos.erase(val);
elements.pop_back();
return true;
}
/** Get a random element from the set. */
int getRandom() {
return elements[rand() % elements.size()];
}
private:
vector elements;
unordered_map pos;
};
// Insert Delete GetRandom O(1) - Duplicates allowed
// 56 ms
class RandomizedCollection {
private:
struct CacheNode {
int frequency;
list pos;
unordered_map::iterator> posCache;
CacheNode() {} // Important!: 要保留默认构造函数
CacheNode(int f, int p) {
frequency = f;
pos.push_back(p);
posCache[p] = --pos.end(); // Important!: 没有pos.end() - 1,pos.end()--也是错的
}
void inc(int p) {
frequency++;
pos.push_back(p);
posCache[p] = --pos.end();
}
int dec() {
frequency--;
int p = pos.back();
pos.pop_back();
posCache.erase(p);
return p;
}
void update(int p, int q) {
pos.erase(posCache[p]);
posCache.erase(p);
pos.push_back(q);
posCache[q] = --pos.end();
}
};
public:
/** Initialize your data structure here. */
RandomizedCollection() {
size = 0;
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val) {
elements.push_back(val);
if (cache.find(val) != cache.end()) {
cache[val].inc(size++);
return false;
} else {
cache[val] = CacheNode(1, size++); // 因为这里会先调用默认构造函数,再调用operator =
return true;
}
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val) {
if (cache.find(val) == cache.end())
return false;
int p = cache[val].dec();
if (cache[val].frequency == 0)
cache.erase(val);
if (p < size - 1) {
int replace_val = elements[size - 1];
elements[p] = replace_val;
cache[replace_val].update(size - 1, p);
}
elements.pop_back();
size--;
return true;
}
/** Get a random element from the collection. */
int getRandom() {
return elements[rand() % size];
}
private:
unordered_map cache;
vector elements;
int size;
};
// All O`one Data Structure
class AllOne {
public:
struct CacheNode {
int value;
list keys;
CacheNode() {}
CacheNode(int v, string key) : value(v) { keys.push_back(key); }
};
/** Initialize your data structure here. */
AllOne() {
}
/** Inserts a new key with value 1. Or increments an existing key by 1. */
void inc(string key) {
if (index1.find(key) == index1.end()) {
if (cache.empty() || cache.front().value > 1)
cache.push_front(CacheNode(1, key));
else
cache.front().keys.push_front(key);
index1[key] = cache.begin();
index2[key] = cache.front().keys.begin();
} else {
list::iterator iter1 = index1[key];
list::iterator iter2 = index2[key];
int value = iter1->value;
iter1->keys.erase(iter2);
if (iter1->keys.empty())
iter1 = cache.erase(iter1);
else
iter1++;
if (iter1 == cache.end() || iter1->value > value + 1)
iter1 = cache.insert(iter1, CacheNode(value + 1, key));
else
iter1->keys.push_front(key);
index1[key] = iter1;
index2[key] = iter1->keys.begin();
}
}
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
void dec(string key) {
if (index1.find(key) != index1.end()) {
list::iterator iter1 = index1[key];
list::iterator iter2 = index2[key];
int value = iter1->value;
iter1->keys.erase(iter2);
if (iter1->keys.empty())
iter1 = cache.erase(iter1);
if (value == 1) {
index1.erase(key);
index2.erase(key);
return;
}
if (iter1 == cache.begin()) {
cache.push_front(CacheNode(value - 1, key));
iter1 = cache.begin();
} else if ((--iter1)->value < value - 1) {
iter1 = cache.insert(++iter1, CacheNode(value - 1, key));
} else {
iter1->keys.push_front(key);
}
index1[key] = iter1;
index2[key] = iter1->keys.begin();
}
}
/** Returns one of the keys with maximal value. */
string getMaxKey() {
return cache.back().keys.front();
}
/** Returns one of the keys with Minimal value. */
string getMinKey() {
return cache.front().keys.front();
}
private:
list cache;
unordered_map::iterator> index1;
unordered_map::iterator> index2;
};
// Peeking Iterator
// Since Iterator has a copy constructor, we can just use it
// Below is the interface for Iterator, which is already defined for you.
// **DO NOT** modify the interface for Iterator.
class Iterator {
struct Data;
Data* data;
public:
Iterator(const vector& nums);
Iterator(const Iterator& iter);
virtual ~Iterator();
// Returns the next element in the iteration.
int next();
// Returns true if the iteration has more elements.
bool hasNext() const;
};
class PeekingIterator : public Iterator {
public:
PeekingIterator(const vector& nums) : Iterator(nums) {
// Initialize any member here.
// **DO NOT** save a copy of nums and manipulate it directly.
// You should only use the Iterator interface methods.
}
// Returns the next element in the iteration without advancing the iterator.
int peek() {
return Iterator(*this).next();
}
// hasNext() and next() should behave the same as in the Iterator interface.
// Override them if needed.
int next() {
return Iterator::next();
}
bool hasNext() const {
return Iterator::hasNext();
}
};
// Min Stack
class MinStack {
private:
struct StackNode {
int value;
int min;
StackNode *next;
StackNode(int value, int min, StackNode *next) : value(value), min(min), next(next) {}
};
StackNode *head;
public:
/** initialize your data structure here. */
MinStack() {
head = NULL;
}
void push(int x) {
if (head == NULL)
head = new StackNode(x, x, NULL);
else {
head = new StackNode(x, min(x, getMin()), head);
}
}
void pop() {
if (head) {
StackNode *newhead = head->next;
free(head);
head = newhead;
}
}
int top() {
if (head)
return head->value;
}
int getMin() {
if (head)
return head->min;
}
};
class MinStack {
private:
stack s1;
stack s2;
public:
void push(int x) {
s1.push(x);
if (s2.empty() || x <= getMin()) s2.push(x);
}
void pop() {
if (s1.top() == getMin()) s2.pop();
s1.pop();
}
int top() {
return s1.top();
}
int getMin() {
return s2.top();
}
};
// Implement Queue using Stacks
class MyQueue {
public:
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
input.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
int result = peek();
output.pop();
return result;
}
/** Get the front element. */
int peek() {
if (output.empty())
transfer();
return output.top();
}
/** Returns whether the queue is empty. */
bool empty() {
return input.empty() && output.empty();
}
void transfer() {
while (!input.empty()) {
output.push(input.top());
input.pop();
}
}
private:
stack input, output;
};
// Implement Stack using Queues
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
q.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
queue p;
while (q.size() > 1) {
p.push(q.front());
q.pop();
}
int result = q.front();
q = p;
return result;
}
/** Get the top element. */
int top() {
int result;
queue p;
while (!q.empty()) {
result = q.front();
p.push(q.front());
q.pop();
}
q = p;
return result;
}
/** Returns whether the stack is empty. */
bool empty() {
return q.empty();
}
private:
queue q;
};
// Flatten Nested List Iterator
class NestedIterator {
public:
NestedIterator(vector &nestedList) {
initialize(nestedList);
pos = 0;
}
int next() {
return vec[pos++];
}
bool hasNext() {
return pos != vec.size();
}
private:
vector vec;
int pos;
void initialize(vector &nestedList) {
for (NestedInteger i : nestedList) {
if (i.isInteger())
vec.push_back(i.getInteger());
else
initialize(i.getList());
}
}
};
class NestedIterator {
public:
NestedIterator(vector &nestedList) {
if (!nestedList.empty()) {
s.push(make_pair(nestedList.begin(), nestedList.end()));
adjust();
}
}
int next() {
vector::iterator ib = s.top().first, ie = s.top().second, iter;
s.pop();
int res = ib->getInteger();
ib++;
if (ib != ie)
s.push(make_pair(ib, ie));
adjust();
return res;
}
bool hasNext() {
return !s.empty();
}
private:
stack::iterator, vector::iterator>> s;
void adjust() {
while (!s.empty() && !s.top().first->isInteger()) {
vector::iterator ib = s.top().first, ie = s.top().second, iter;
s.pop();
iter = ib;
ib++;
if (ib != ie)
s.push(make_pair(ib, ie));
if (!iter->getList().empty())
s.push(make_pair(iter->getList().begin(), iter->getList().end()));
}
}
};
class NestedIterator {
public:
NestedIterator(vector &nestedList) {
s.push(make_pair(nestedList.begin(), nestedList.end()));
adjust();
}
int next() {
int res = s.top().first->getInteger();
s.top().first++;
adjust();
return res;
}
bool hasNext() {
return !s.empty();
}
private:
stack::iterator, vector::iterator>> s;
void adjust() {
while (!s.empty()) {
if (s.top().first == s.top().second) {
s.pop();
} else {
if (s.top().first->isInteger())
break;
vector::iterator iter = s.top().first;
s.top().first++;
s.push(make_pair(iter->getList().begin(), iter->getList().end()));
}
}
}
};
// Binary Search Tree Iterator
class BSTIterator {
public:
BSTIterator(TreeNode *root) {
TreeNode *p = root;
while (p) {
s.push(p);
p = p->left;
}
}
/** @return whether we have a next smallest number */
bool hasNext() {
return !s.empty();
}
/** @return the next smallest number */
int next() {
int res = s.top()->val;
TreeNode *p = s.top()->right;
if (p) {
while (p) {
s.push(p);
p = p->left;
}
} else {
p = s.top();
s.pop();
while (!s.empty() && p == s.top()->right) {
p = s.top();
s.pop();
}
}
return res;
}
private:
stack s;
};
class BSTIterator {
public:
BSTIterator(TreeNode *root) {
TreeNode *p = root;
while (p) {
s.push(p);
p = p->left;
}
}
/** @return whether we have a next smallest number */
bool hasNext() {
return !s.empty();
}
/** @return the next smallest number */
int next() {
int res = s.top()->val;
TreeNode *p = s.top()->right;
s.pop();
while (p) {
s.push(p);
p = p->left;
}
return res;
}
private:
stack s;
};
// Flatten 2D Vector
class Vector2D {
public:
Vector2D(vector>& vec2d) {
x = vec2d.begin();
end = vec2d.end();
}
int next() {
return (*x)[y++];
}
bool hasNext() {
while (x != end && y == (*x).size()) {
++x;
y = 0;
}
return x != end;
}
private:
vector>::iterator x, end;
int y = 0;
};