前言
刷题坚持每一天,以下题目引用自:力扣(LeetCode)
💎一、题目一
🏆1.题目描述
原题链接:432. 全 O(1) 的数据结构
请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。
实现 AllOne 类:
- AllOne() 初始化数据结构的对象。
- inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。
- dec(String key) 字符串 key 的计数减少 1 。如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。
- getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 “” 。
- getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 “” 。
注意:每个函数都应当满足 O(1) 平均时间复杂度。
示例 1:
输入
[“AllOne”, “inc”, “inc”, “getMaxKey”, “getMinKey”, “inc”, “getMaxKey”, “getMinKey”]
[[], [“hello”], [“hello”], [], [], [“leet”], [], []]
输出
[null, null, null, “hello”, “hello”, null, “hello”, “leet”]
解释
AllOne allOne = new AllOne();
allOne.inc(“hello”);
allOne.inc(“hello”);
allOne.getMaxKey(); // 返回 “hello”
allOne.getMinKey(); // 返回 “hello”
allOne.inc(“leet”);
allOne.getMaxKey(); // 返回 “hello”
allOne.getMinKey(); // 返回 “leet”
🏆2.解题思路
🔑思路:
双向链表+hash,字符串为键用于查找,每个哈希值对应一个链表节点。插入操作在hash里不存在创建新节点存于表头,若存在当前节点计数加1并和下一节点比较字符串的数量,小于下一节点不做处理,大于下一节点和下一节点做交换处理。删除操作对字符串计数减1,处理完数量为零则删除当前节点并更新头节点,处理完数量不为零则和上一节点比较字符串数量,大于上一节点不做处理,小于上一节点和上一节点做交换处理。
🏆3.代码详解
struct Listnode{
string key;
int count;
Listnode* prev;
Listnode* next;
Listnode(){
prev = next = NULL;
}
};
class AllOne {
Listnode* head;
Listnode* tail;
unordered_map<string, Listnode*> hash;
public:
AllOne() {
head = tail = NULL;
hash.clear();
}
void inc(string key) {
auto replase = hash.find(key);
Listnode* node;
if(replase == hash.end()){
node = new Listnode();
node->key = key;
node->count = 1;
hash[key] = node;
if(head == NULL){
head = tail = node;
}
else{
head->prev = node;
node->next = head;
head = head->prev;
}
}
else{
node = replase->second;
node->count++;
}
while(node && node->next){
if(node->count > node->next->count){
Listnode* nextnode = node->next;
string temp = node->key;
node->key = nextnode->key;
nextnode->key = temp;
int tcount = node->count;
node->count = nextnode->count;
nextnode->count = tcount;
Listnode* centrce = hash[node->key];
hash[node->key] = hash[nextnode->key];
hash[nextnode->key] = centrce;
}
node = node->next;
}
}
void dec(string key) {
auto replase = hash.find(key);
Listnode* node = replase->second;
node->count--;
if(node->count == 0){
if(node->next) node->next->prev = node->prev;
else tail = node->prev;
if(node->prev) node->prev->next = node->next;
else head = node->next;
}
else{
while(node && node->prev){
if(node->count < node->prev->count){
Listnode* prevnode = node->prev;
string temp = node->key;
node->key = prevnode->key;
prevnode->key = temp;
int tcount = node->count;
node->count = prevnode->count;
prevnode->count = tcount;
Listnode* centrce = hash[node->key];
hash[node->key] = hash[prevnode->key];
hash[prevnode->key] = centrce;
}
node = node->prev;
}
}
}
string getMaxKey() {
if(tail == NULL) return "";
return tail->key;
}
string getMinKey() {
if(head == NULL) return "";
return head->key;
}
};
💎二、星球推荐
星球链接:英雄算法联盟
星球里有什么?
【朋友圈】一个极致精准的自律、编程、算法的小圈子。
【算法集训】以月为单位组织算法集训,每天四题,风雨无阻。
【排行榜】每天、每周都会有榜单,激励大家不断进步,不断成长。
【个人规划】每个人都写好自己的规划,也可以查看他人的规划,时刻警醒自己不掉队。
【打卡挑战】每日一题打卡、每日早起打卡、算法集训打卡、规划完成情况打卡。
在星球里做什么?
目前星球人数达到520+,在星球里你能够遇到一群志同道合之人,因为都是花钱进来的,你不会看到任何浑水摸鱼的人,每个人都有自己的每月规划,星主每月都会组织算法集训,每天一起刷题,你可以看到别人的解题报告,取其之长,补己之短。