目录
381. O(1) 时间插入、删除和获取随机元素 - 允许重复
LRU:
struct Node {
Node *l, *r;
int key, val;
Node(int _key, int _val) :key(_key), val(_val) {}
}*head, *tail; //两个哨兵
class LRUCache {
public:
int n;
unordered_map<int, Node*> hash;
//从双链表删除掉p节点
void remove(Node* p) {
p -> l -> r = p -> r;
p -> r -> l = p -> l;
}
//在头部(head后)插入p节点
void insert(Node* p) {
p -> l = head;
p -> r = head -> r;
head -> r = p;
p -> r -> l = p;
}
LRUCache(int capacity) {
n = capacity;
head = new Node(-1, -1);
tail = new Node(-1, -1);
head -> r = tail;
tail -> l = head;
}
int get(int key) {
if (!hash.count(key)) return -1;
Node* p = hash[key];
//使用过一次,把他插入到链表的头部
remove(p);
insert(p);
return p -> val;
}
void put(int key, int value) {
if (hash.count(key)) {
hash[key] -> val = value;
Node* p = hash[key];
remove(p);
insert(p);
} else {
if (hash.size() == n) {
Node* p = tail -> l;
remove(p);
hash.erase(p -> key);
delete p;
}
Node* q = new Node(key, value);
hash[key] = q;
insert(q);
}
}
};
LFU:
//双链表套双链表
//每一个block表示所有访问次数相同的点
//每一个blcok内有多个node,头结点是最近被访问的节点
class LFUCache {
public :
struct Node {
Node *left, *right;
int key, val;
Node(int _key, int _val) {
this -> key = _key;
this -> val = _val;
left = right = NULL;
}
};
struct Block {
Block *left, *right;
Node *head, *tail; //每个块内的头尾节点
int cnt;//这个块内所有节点都是被访问了cnt次
Block(int _cnt) {
this -> cnt = _cnt;
left = right = NULL;
head = new Node(-1, -1), tail = new Node(-1, -1);//为了代码方便,维护两个哨兵
head -> right = tail, tail -> left = head;
}
~Block() {
delete head;
delete tail;
}
void insert(Node *p) {
//插入到块内的第一个节点
p -> right = head -> right;
head -> right -> left = p;
head -> right = p;
p -> left = head;
}
void remove(Node *p) {
p -> left -> right = p -> right;
p -> right -> left = p -> left;
}
bool empty() {
return head -> right == tail;
}
}*head, *tail;// 维护两个哨兵
int n;
unordered_map<int, Block*> hash_block;
unordered_map<int, Node*> hash_node;
void insert(Block *p) {
//在p的右侧插入一个新块,cnt为当前块的cnt+1
auto cur = new Block(p -> cnt + 1);
cur -> right = p -> right;
p -> right -> left = cur;
p -> right = cur;
cur -> left = p;
}
void remove(Block* p) {
p -> left -> right = p -> right;
p -> right -> left = p -> left;
delete p;
}
LFUCache(int capacity) {
this -> n = capacity;
head = new Block(0), tail = new Block(INT_MAX);
head -> right = tail, tail -> left = head;
}
int get(int key) {
if (hash_block.count(key) == 0) return -1;
auto block = hash_block[key];
auto node = hash_node[key];
block -> remove(node);
if (block -> right -> cnt != block -> cnt + 1) insert(block);
block -> right -> insert(node);
hash_block[key] = block -> right;
if (block -> empty()) remove(block);
return node -> val;
}
void put(int key, int value) {
if (n == 0) return ;
if (hash_block.count(key)) {
hash_node[key] -> val = value;
get(key);//更新一次cnt
} else {
if (hash_block.size() == n) {
auto p = head -> right -> tail -> left;
head -> right -> remove(p);
if (head -> right -> empty()) remove(head -> right);
hash_block.erase(p -> key);
hash_node.erase(p -> key);
delete p;
}
auto p = new Node(key, value);
if (head -> right -> cnt != 1) insert(head);
head -> right -> insert(p);
hash_block[key] = head -> right;
hash_node[key] = p;
}
}
};
380. O(1) 时间插入、删除和获取随机元素
class RandomizedSet {
public:
/** Initialize your data structure here. */
unordered_map<int, int> hash;
vector<int> nums;
RandomizedSet() {
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int x) {
if (hash.count(x) == 0) {
nums.push_back(x);
hash[x] = nums.size() - 1;
return true;
}
return false;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int x) {
if (hash.count(x)) {
int y = nums.back();
int px = hash[x], py = hash[y];
swap(nums[px], nums[py]);
swap(hash[x], hash[y]);
nums.pop_back();
hash.erase(x);
return true;
}
return false;
}
/** Get a random element from the set. */
int getRandom() {
return nums[rand() % nums.size()];
}
};
381. O(1) 时间插入、删除和获取随机元素 - 允许重复
class RandomizedCollection {
public:
unordered_map<int, unordered_set<int>> hash;
vector<int> nums;
/** Initialize your data structure here. */
RandomizedCollection() {
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int x) {
bool res = hash[x].empty();
nums.push_back(x);
hash[x].insert(nums.size() - 1);
return res;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int x) {
if (hash[x].size()) {
int px = *hash[x].begin(), py = nums.size() - 1;
int y = nums.back();
swap(nums[px], nums[py]);
hash[x].erase(px), hash[x].insert(py);
hash[y].erase(py), hash[y].insert(px);
nums.pop_back();
hash[x].erase(py);
return true;
}
return false;
}
/** Get a random element from the collection. */
int getRandom() {
return nums[rand() % nums.size()];
}
};