C++算法:全 O(1) 的数据结构

简介: C++算法:全 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) 平均时间复杂度。

示例:

输入

[“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 <= 10

key 由小写英文字母组成

测试用例保证:在每次调用 dec 时,数据结构中总存在 key

最多调用 inc、dec、getMaxKey 和 getMinKey 方法 5 * 104 次

2023年5月版

class AllOne {
public:
AllOne() {
}
void inc(string key) {
int iPreNum = m_mStrNums[key];
m_mStrNums[key]++;
if (iPreNum > 0)
{
auto it = m_mNumStrs[iPreNum].find(key);
m_mNumStrs[iPreNum].erase(it);
if (m_mNumStrs[iPreNum].empty())
{
m_mNumStrs.erase(iPreNum);
}
}
m_mNumStrs[iPreNum + 1].emplace(key);
}
void dec(string key) {
int iPreNum = m_mStrNums[key];
m_mStrNums[key]–;
auto it = m_mNumStrs[iPreNum].find(key);
m_mNumStrs[iPreNum].erase(it);
if (m_mNumStrs[iPreNum].empty())
{
m_mNumStrs.erase(iPreNum);
}
if (iPreNum > 1)
{
m_mNumStrs[iPreNum - 1].emplace(key);
}
}
string getMaxKey() {
if (m_mNumStrs.empty())
{
return “”;
}
return *m_mNumStrs.rbegin()->second.begin();
}
string getMinKey() {
if (m_mNumStrs.empty())
{
return “”;
}
return *m_mNumStrs.begin()->second.begin();
}
std::unordered_map<string, int> m_mStrNums;
std::map<int ,std::unordered_multiset> m_mNumStrs;
};

2023年8月版

class AllOne {
public:
AllOne() {
}
void inc(string key) {
if (m_mStrNum.count(key))
{
auto it = m_mStrNum[key];
const int iNewNum = it->first + 1;
auto ij = it;
++ij;
it->second.erase(key);
if (0 == it->second.size())
{
m_list.erase(it);
}
bool bNeedAdd = true;
if (m_list.end() != ij )
{
bNeedAdd = iNewNum != ij->first;
}
if (bNeedAdd)
{
ij = m_list.emplace(ij, iNewNum, std::set{key});
}
else
{
ij->second.emplace(key);
}
m_mStrNum[key] = ij;
}
else
{
bool bNeedAdd = true;
auto it = m_list.begin();
if (it != m_list.end())
{
bNeedAdd = 1 != it->first;
}
if (bNeedAdd)
{
it = m_list.emplace(m_list.begin(), 1, std::set{key});
}
else
{
it->second.emplace(key);
}
m_mStrNum[key] = m_list.begin();
}
}
void dec(string key) {
auto it = m_mStrNum[key];
const int iNewNum = it->first - 1;
if (m_list.begin() != it)
{
auto ij = it;
–ij;
if (ij->first == iNewNum)
{
it->second.erase(key);
if (0 == it->second.size())
{
m_list.erase(it);
}
ij->second.emplace(key);
if (0 == iNewNum)
{
m_mStrNum.erase(key);
}
else
{
m_mStrNum[key] = ij;
}
return;
}
}
if (0 == iNewNum)
{
m_mStrNum.erase(key);
}
else
{
it = m_list.emplace(it, iNewNum, set{key});
m_mStrNum[key] = it;
++it;
}
it->second.erase(key);
if (0 == it->second.size())
{
it = m_list.erase(it);
}
}
string getMaxKey() {
if (m_list.rbegin() == m_list.rend())
{
return “”;
}
return *m_list.rbegin()->second.begin();
}
string getMinKey() {
if (m_list.begin() == m_list.end())
{
return “”;
}
return *m_list.begin()->second.begin();
}
typedef std::list < std::pair<int, std::set>> LIST;
std::unordered_map<string, LIST::iterator> m_mStrNum;
LIST m_list;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

洒家想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
墨家名称的来源:有所得以墨记之。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境:

VS2022 C++17


相关文章
|
2月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
51 1
|
2月前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
131 4
|
13天前
|
存储 运维 监控
探索局域网电脑监控软件:Python算法与数据结构的巧妙结合
在数字化时代,局域网电脑监控软件成为企业管理和IT运维的重要工具,确保数据安全和网络稳定。本文探讨其背后的关键技术——Python中的算法与数据结构,如字典用于高效存储设备信息,以及数据收集、异常检测和聚合算法提升监控效率。通过Python代码示例,展示了如何实现基本监控功能,帮助读者理解其工作原理并激发技术兴趣。
50 20
|
5天前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
3天前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
10天前
|
算法 安全 C++
用 C++ 算法控制员工上网的软件,关键逻辑是啥?来深度解读下
在企业信息化管理中,控制员工上网的软件成为保障网络秩序与提升办公效率的关键工具。该软件基于C++语言,融合红黑树、令牌桶和滑动窗口等算法,实现网址精准过滤、流量均衡分配及异常连接监测。通过高效的数据结构与算法设计,确保企业网络资源优化配置与安全防护升级,同时尊重员工权益,助力企业数字化发展。
32 4
|
2月前
|
存储 算法 搜索推荐
Python 中数据结构和算法的关系
数据结构是算法的载体,算法是对数据结构的操作和运用。它们共同构成了计算机程序的核心,对于提高程序的质量和性能具有至关重要的作用
|
2月前
|
数据采集 存储 算法
Python 中的数据结构和算法优化策略
Python中的数据结构和算法如何进行优化?
|
2月前
|
算法
数据结构之路由表查找算法(深度优先搜索和宽度优先搜索)
在网络通信中,路由表用于指导数据包的传输路径。本文介绍了两种常用的路由表查找算法——深度优先算法(DFS)和宽度优先算法(BFS)。DFS使用栈实现,适合路径问题;BFS使用队列,保证找到最短路径。两者均能有效查找路由信息,但适用场景不同,需根据具体需求选择。文中还提供了这两种算法的核心代码及测试结果,验证了算法的有效性。
112 23
|
2月前
|
算法
数据结构之蜜蜂算法
蜜蜂算法是一种受蜜蜂觅食行为启发的优化算法,通过模拟蜜蜂的群体智能来解决优化问题。本文介绍了蜜蜂算法的基本原理、数据结构设计、核心代码实现及算法优缺点。算法通过迭代更新蜜蜂位置,逐步优化适应度,最终找到问题的最优解。代码实现了单链表结构,用于管理蜜蜂节点,并通过适应度计算、节点移动等操作实现算法的核心功能。蜜蜂算法具有全局寻优能力强、参数设置简单等优点,但也存在对初始化参数敏感、计算复杂度高等缺点。
63 20