LeetCode 432. 全 O(1) 的数据结构
LeetCode 432. 全 O(1) 的数据结构
难度:hard\color{red}{hard}hard
题目描述
请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。
实现 AllOneAllOneAllOne 类:
- AllOne()AllOne()AllOne() 初始化数据结构的对象。
- inc(Stringkey)inc(String key)inc(Stringkey) 字符串 keykeykey 的计数增加 111 。如果数据结构中尚不存在 keykeykey ,那么插入计数为 111 的 keykeykey 。
- dec(Stringkey)dec(String key)dec(Stringkey) 字符串 keykeykey 的计数减少 111 。如果 keykeykey 的计数在减少后为 000 ,那么需要将这个 keykeykey 从数据结构中删除。测试用例保证:在减少计数前,keykeykey 存在于数据结构中。
- getMaxKey()getMaxKey()getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 """""" 。
- getMinKey()getMinKey()getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 """""" 。
注意: 每个函数都应当满足 O(1)O(1)O(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"
提示:
- 1<=key.length<=101 <= key.length <= 101<=key.length<=10
- keykeykey 由小写英文字母组成
- 测试用例保证:在每次调用 decdecdec 时,数据结构中总存在 keykeykey
- 最多调用 incincinc、decdecdec、getMaxKeygetMaxKeygetMaxKey 和 getMinKeygetMinKeygetMinKey 方法 5∗1045 * 10^{4}5∗104 次
算法
(哈希表,双向链表)
- 定义结构体
Node
,记录值value
和所有等于该值的字符串集合。 - 维护一个哈希表,每个
key
对应的一个Node
类型的指针。 Node
结构按值的顺序组成双向链表。初始时有值为INT_MIN
和值为INT_MAX
的两个哨兵结点。- 对于插入操作,如果哈希表中不存在,则在哈希表中添加
h[key] = new node(val)
。从哈希表中取出当前结构体,将这个key
添加到下一个结构体中(如果不存在则新建立结点),并在当前结构体中删除key
。 - 对于删除,同理进行移动
key
的操作。 - 取最大最小值时,直接取链表的头或尾所对应的的字符串集合。
复杂度分析
-
时间复杂度:O(1)O(1)O(1)
-
空间复杂度 : O(n)O(n)O(n)
C++ 代码
class AllOne {
public://创建一个双链表,其中有左右指针struct Node {Node *left, *right;int val;unordered_set<string> S;Node(int _val) {val = _val;left = right = NULL;}}*left, *right;// 创建一个哈希表unordered_map<string, Node*> hash;//初始化双链表最左边的节点和最右边的节点AllOne() {left = new Node(INT_MIN), right = new Node(INT_MAX);right->left = left, left->right = right;}//在节点的右边插入一个新的节点Node* add_to_right(Node *node, string key, int val) {if (node->right->val == val) node->right->S.insert(key);else {auto t = new Node(val);t->S.insert(key);t->right = node->right, node->right->left = t;node->right = t, t->left = node;}return node->right;}//在节点的左边边插入一个新的节点Node* add_to_left(Node *node, string key, int val) {if (node->left->val == val) node->left->S.insert(key);else {auto t = new Node(val);t->S.insert(key);t->left = node->left, node->left->right = t;node->left = t, t->right = node;}return node->left;}//删除一个节点void remove(Node* node) {node->left->right = node->right;node->right->left = node->left;delete node;}void inc(string key) {//如果该节点计数为0,在最左边插入一个值为1的节点if (hash.count(key) == 0) hash[key] = add_to_right(left, key, 1);else {//向右插入一个新的节点auto t = hash[key];t->S.erase(key);hash[key] = add_to_right(t, key, t->val + 1);if (t->S.empty()) remove(t);}}void dec(string key) {if (hash.count(key) == 0) return;auto t = hash[key];t->S.erase(key);if (t->val > 1) {hash[key] = add_to_left(t, key, t->val - 1);} else {hash.erase(key);}if (t->S.empty()) remove(t);}string getMaxKey() {if (right->left != left) return *right->left->S.begin();return "";}string getMinKey() {if (left->right != right) return *left->right->S.begin();return "";}
};/*** 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();*/
修改变量版本:
class AllOne {
public:struct Node {Node *pre, *nxt;int value;unordered_set<string> keys;Node (int val) {value = val;pre = nxt = NULL;}}*left, *right;unordered_map<string, Node*> hash;AllOne() {left = new Node(0);right = new Node(INT_MAX);left->nxt = right;right->pre = left;}Node* add_to_right(Node* node, string key, int val) {if (node->nxt->value == val) node->nxt->keys.insert(key);else {auto t = new Node(val);t->keys.insert(key);t->nxt = node->nxt, node->nxt->pre = t;t->pre = node, node->nxt = t;}return node->nxt;}Node* add_to_left(Node* node, string key, int val) {if (node->pre->value == val) node->pre->keys.insert(key);else {auto t = new Node(val);t->keys.insert(key);node->pre->nxt = t, t->nxt = node;t->pre = node->pre, node->pre = t;}return node->pre;}void remove(Node *node) {node->pre->nxt = node->nxt;node->nxt->pre = node->pre;delete node;}void inc(string key) {if (hash.count(key) == 0) hash[key] = add_to_right(left, key, 1);else {auto t = hash[key];t->keys.erase(key);hash[key] = add_to_right(t, key, t->value + 1);if (t->keys.empty()) remove(t);}}void dec(string key) {if (hash.count(key) == 0) return;auto t = hash[key];t->keys.erase(key);if (t->value > 1) {hash[key] = add_to_left(t, key, t->value - 1);} else {hash.erase(key);}if (t->keys.empty()) remove(t);}string getMaxKey() {if (left->nxt != right) return *right->pre->keys.begin();return "";}string getMinKey() {if (right->pre != left) return *left->nxt->keys.begin();return "";}
};/*** 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();*/
相关文章:
LeetCode 432. 全 O(1) 的数据结构
LeetCode 432. 全 O(1) 的数据结构 难度:hard\color{red}{hard}hard 题目描述 请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。 实现 AllOneAllOneAllOne 类: AllOne()AllOne()AllOne() 初始化数据结构的对…...

再析jvm
前言 希望自己每一次学习都有不同的理解 文章目录前言1. jvm的组成取消永久代使用元空间原因2. 运行时数据区3. 堆栈区别队列和栈,队列先进先出,栈先进后出从栈顶弹出4. GC、内存溢出、垃圾回收4.1 如何确定引用是否会被回收4.1.1 Java中的引用类型4.1.…...
社招前端二面面试题总结
代码输出结果 var A {n: 4399}; var B function(){this.n 9999}; var C function(){var n 8888}; B.prototype A; C.prototype A; var b new B(); var c new C(); A.n console.log(b.n); console.log(c.n);输出结果:9999 4400 解析: conso…...

人人能读懂redux原理剖析
一、Redux是什么? 众所周知,Redux最早运用于React框架中,是一个全局状态管理器。Redux解决了在开发过程中数据无限层层传递而引发的一系列问题,因此我们有必要来了解一下Redux到底是如何实现的? 二、Redux的核心思想…...

uniCloud云开发----7、uniapp通过uni-swiper-dot实现轮播图
uniapp通过uni-swiper-dot实现轮播图前言效果图1、官网实现的效果2、需求中使用到的效果图官网提供的效果图源码1、html部分2、js部分3、css部分根据需求调整轮播图前言 uni-swiper-dot.文档 uni-swiper-dot 轮播图指示点 - DCloud 插件市场 本次展示根据需求制作的和官网用到…...

IM即时通讯构建企业协同生态链
在当今互联网信息飞速发展的时代,随着企业对协同办公要求的提高,协同办公的定义提升到了智能化办公的范畴。大多企业都非常重视构建连接用户、员工和合作伙伴的生态平台,利用即时通讯软件解决企业内部的工作沟通、信息传递和知识共享等问题。…...
Python实现构建gan模型, 输入一个矩阵和两个参数值,输出一个矩阵
构建一个GAN模型,使用Python实现,该模型将接受一个矩阵和两个参数值作为输入,并输出另一个矩阵。GAN(生成对抗网络)是一种深度学习模型,由生成器和判别器两部分组成,可以用于生成具有一定规律性的数据,如图像或音频。 # 定义生成器 def make_generator(noise_dim, dat…...
开学准备哪些电容笔?ipad触控笔推荐平价
在现代,数码产品的发展受到高技术的驱动。不管是在工作上,还是在学习上,大的显示屏可以使图像更加清晰。Ipad将成为我们日常生活中不可或缺的一部分,无论现在或将来。如果ipad配上一款方便操作的电容笔,将极大地提高我…...
放下和拿起 解放自己
放下太难,从过去中解放自己 工作这么久了,第一次不拿包上班,真爽 人的成长都是在碰撞和摸索中产生的,通过摸索,知道自己能力的边界和欲望的边界以及身体的边界,这三个决定了 你能做什么 你能享受什么&…...

100%BIM学员的疑惑:不会CAD可以学Revit吗?
在新一轮科技创新和产业变革中,信息化与建筑业的融合发展已成为建筑业发展的方向,将对建筑业发展带来战略性和全局性的影响。 建筑业是传统产业,推动建筑业科技创新,加快推进信息化发展,激发创新活力,培育…...

经常会采坑的javascript原型应试题
一. 前言 原型和原型链在面试中历来备受重视,经常被提及。说难可能也不太难,但要真正完全理解,吃透它,还是要多下功夫的。 下面为大家简单阐述我对原型和原型链的理解,若是觉得有说的不对的地方ÿ…...

完全背包—动态规划
一、背包问题概述 如图,完全背包与01背包的区别只有一点:01背包中每个物品只能取一个而完全背包中每个物品可以取无数个。解决完全背包问题必须首先弄明白01背包,不清楚的可以看我的这篇文章01背包—动态规划。 二、例题 重量价值物品0115物…...

消息队列MQ介绍
消息队列技术是分布式应用间交换信息的一种技术。消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走。通过消息队列,应用程序可独立地执行--它们不需要知道彼此的位置、或在继续执行前不需要等待接收程序接收此消息。 消息中间件概述 消息队列技术是…...

C语言进阶(八)—— 链表
1. 链表基本概念1.1 什么是链表链表是一种常用的数据结构,它通过指针将一些列数据结点,连接成一个数据链。相对于数组,链表具有更好的动态性(非顺序存储)。数据域用来存储数据,指针域用于建立与下一个结点的…...

手工测试用例就是自动化测试脚本——使用ruby 1.9新特性进行自动化脚本的编写
昨天因为要装watir-webdriver的原因将用了快一年的ruby1.8.6升级到了1.9。由于1.9是原生支持unicode编码,所以我们可以使用中文进行自动化脚本的编写工作。 做了简单的封装后,我们可以实现如下的自动化测试代码。请注意,这些代码是可以正确运…...

RockerMQ简介和单节点部署
目录一、RockerMQ简介二、Linux中单节点部署1、准备工作2、下载和解压3、修改初始内存4、启动5、查看进程6、发送接收消息测试7、关闭三、控制台的安装与启动(可视化页面)1、修改配置(1)修改端口号(2)指定RocketMQ的name server地…...

SFP光纤笼子 别称 作用 性能要点 工程要素
Hqst盈盛电子导读:2023年,Hqst盈盛电子于下属五金部开发生产SFP光纤连接器笼子等系列产品,所有产品生产及性标准都将参照连接器产品常用测试标准EIA-364-C等标准,以下为我司常规SFP光纤连接器基本性能要求SFP光纤笼子别称…...

[HarekazeCTF2019]Easy Notes
知识点:session 反序列化,代码审计代码分析 flag.php 中有个 is_admin 函数的判断。 在 lib.php 中有 is_admin 函数,需要 session[admin] 为 true,或者通过文件读取的方式。 在 index.php 中的 include 并不能使用伪协议读取 …...
Java学习-IO流-字符流-FileReader
Java学习-IO流-字符流-FileReader 字符流 字节流 字符集 输入流:默认一次读一个字节,遇到中文时一次读多个字节 输出流:底层把数据按照指定编码方式编码,变成字节写入文件 使用场景:纯文本文件读写 // …...

python攻陷米哈游《元神》数据?详情请看文章。。
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 《原神》是由米哈游自研的一款全新开放世界冒险RPG。 里面拥有许多丰富得角色,让玩家为之着迷~ 今天,我们就来用python探索一下原神游戏角色信息! 标题大家看看就好了哈~(…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...

PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...