六月集训(第13天)—双向链表
双向链表
1. 432. 全 O(1) 的数据结构
思路:
$O(1)$时间查询,则立刻想到hash表,这题又是双向链表专题的,于是想办法把双向链表和hash表结合起来。
(1) 用双向链表存储键值为key的结点,只需要存一个,再次inc只需要将其对应的count值+1即可
(2) hash表中将key映射到双向链表的结点地址,实现$O(1)$查询
(3) 将双线链表按照每个结点的count值升序排列,设置head和tail指针,实现$O(1)$时间查询Max和Min
(4) 每次inc或者del维护双向链表按照升序排列
struct BiNode {
string key;
int count;
BiNode *prev, *next;
BiNode() {
prev = next = NULL;
}
};
class AllOne {
BiNode *head, *tail;
unordered_map<string, BiNode*> hash;
void swap(string &a, string &b) {
string temp = a;
a = b;
b = temp;
}
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
public:
AllOne() {
head = tail = NULL;
hash.clear();
}
void insert(BiNode *node) {
if (head == NULL) {
head = tail = node;
return ;
}
// 链表头部插入一个结点
head->prev = node;
node->next = head;
head = node;
}
void del(BiNode *node) {
// 修改前一个点的后继
if (node->prev) {
node->prev->next = node->next;
} else {
head =node->next; /* 更新头节点的位置 */
}
// 修改后一个点的前驱
if (node->next) {
node->next->prev = node->prev;
} else {
tail = node->prev; /* 更新尾结点位置 */
}
}
// 向后维持按照key的出现次数,升序排列
void balance_backward(BiNode *node) {
while (node && node->next) {
if (node->count > node->next->count) { /* 链表按照每个key的出现次数,升序排列 */
BiNode *nnext = node->next;
swap(node->key, nnext->key);
swap(node->count, nnext->count);
// 交换hash表中键值映射的结点
BiNode *tmp = hash[node->key];
hash[node->key] = hash[nnext->key];
hash[nnext->key] = tmp;
}
node = node->next;
}
}
// 向前维持按照key的出现次数,升序排列
void balance_foward(BiNode *node) {
while (node && node->prev) {
if (node->count < node->prev->count) {
BiNode *nprev = node->prev;
swap(node->key, nprev->key);
swap(node->count, nprev->count);
BiNode *tmp = hash[node->key];
hash[node->key] = hash[nprev->key];
hash[nprev->key] = tmp;
}
node = node->prev;
}
}
void inc(string key) {
auto iter = hash.find(key);
BiNode *node;
if (iter == hash.end()) { // 如果该键值对应的结点不存在,则创建一个新结点
node = new BiNode();
node->key = key;
node->count = 1;
hash[key] = node;
insert(node);
} else {
node = iter->second;
node->count++;
}
balance_backward(node); // node->count变大了,将其向后维护升序排列
}
void dec(string key) {
auto iter = hash.find(key);
BiNode *node = iter->second;
node->count--;
if (node->count == 0) {
del(node);
} else {
balance_foward(node); // // node->count变小了,将其向前维护升序排列
}
}
string getMaxKey() {
if (tail == NULL) return "";
return tail->key;
}
string getMinKey() {
if (head == NULL) return "";
return head->key;
}
};
/**
* 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();
*/
东方欲晓,莫道君行早。

浙公网安备 33010602011771号