• 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 m_mStrNums;
    std::map 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> LIST;
    std::unordered_map 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

  • 相关阅读:
    单商户商城系统功能拆解36—分销应用—分销商
    【详细学习SpringBoot自动装配原理之自定义手写Starter案例实操实战-2】
    Unity与IOS⭐Unity接入IOS SDK的流程图
    【Redis】使用Java客户端操作Redis
    浅谈Java学习以及学习路线图
    JDK版本切换 - Windows
    JAVA开发(分布式SpringCloud全家桶一些组件读法)
    十天学前端(一)
    Python 毕设精品实战案例——快速索引目录Part2
    TCP链接为什么要必须要四次挥手,为什么链接三次握手即可?
  • 原文地址:https://blog.csdn.net/he_zhidan/article/details/134404322