LeetCode-432. All O`one Data Structure [C++][Java]

本文介绍如何使用AllOne数据结构实现字符串计数,常用于面试准备,支持O(1)复杂度的inc(), dec(), getMaxKey(), getMinKey()操作。通过实例演示了如何在C++和Java中实现这一数据结构,适用于字符串计数场景并优化代码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode-432. All O`one Data StructureLevel up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.https://leetcode.com/problems/all-oone-data-structure/

Design a data structure to store the strings' count with the ability to return the strings with minimum and maximum counts.

Implement the AllOne class:

  • AllOne() Initializes the object of the data structure.
  • inc(String key) Increments the count of the string key by 1. If key does not exist in the data structure, insert it with count 1.
  • dec(String key) Decrements the count of the string key by 1. If the count of key is 0 after the decrement, remove it from the data structure. It is guaranteed that key exists in the data structure before the decrement.
  • getMaxKey() Returns one of the keys with the maximal count. If no element exists, return an empty string "".
  • getMinKey() Returns one of the keys with the minimum count. If no element exists, return an empty string "".

Note that each function must run in O(1) average time complexity.

Example 1:

Input
["AllOne", "inc", "inc", "getMaxKey", "getMinKey", "inc", "getMaxKey", "getMinKey"]
[[], ["hello"], ["hello"], [], [], ["leet"], [], []]
Output
[null, null, null, "hello", "hello", null, "hello", "leet"]

Explanation
AllOne allOne = new AllOne();
allOne.inc("hello");
allOne.inc("hello");
allOne.getMaxKey(); // return "hello"
allOne.getMinKey(); // return "hello"
allOne.inc("leet");
allOne.getMaxKey(); // return "hello"
allOne.getMinKey(); // return "leet"

Constraints:

  • 1 <= key.length <= 10
  • key consists of lowercase English letters.
  • It is guaranteed that for each call to deckey is existing in the data structure.
  • At most 5 * 10^4 calls will be made to incdecgetMaxKey, and getMinKey.

【C++】

class AllOne {
    unordered_map<string,int> m;// store string -> val
    map<int,unordered_set<string>> mp;// val -> set of strings with value as val 
public:
    AllOne() {}

    void inc(string key) {
        if (m.find(key) == m.end())  {
            m[key]=1;
            mp[1].insert(key);
        } else {
            int p=m[key];
            m[key]=p+1;
            mp[p].erase(key);
            if (mp[p].size() == 0) {mp.erase(p);}
            mp[p+1].insert(key);
        }
    }

    void dec(string key) {
        int p=m[key];
        if (p==1) {
            m.erase(key);
            mp[p].erase(key);
            if(mp[p].size()==0) {mp.erase(p);}
        } else {
            m[key]=p-1;
            mp[p].erase(key);
            if (mp[p].size() == 0) {mp.erase(p);}
            mp[p-1].insert(key);
        }
    }

    string getMaxKey() {
        string s="";
        if(mp.size()) {
            auto p=mp.rbegin()->second.begin();
            s=*p;
        }
        return s;
    }
    
    string getMinKey() {
        string s="";
        if (mp.size()) {
            auto p=mp.begin()->second.begin();
            s=*p;
        }
        return s;
    }
};

/**
 * 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();
 */

【Java】

class AllOne {
 static class Bucket {
        int count;
        Set<String> keys;
        Bucket prev;
        Bucket next;
        public Bucket(int count) {
            this.count = count;
            keys = new LinkedHashSet<>();
        }

        public void insertAfter(Bucket newBucket) {
            Bucket nextBucket = this.next;
            this.next = newBucket;
            nextBucket.prev = newBucket;
            newBucket.prev = this;
            newBucket.next = nextBucket;
        }
    }

    private final Map<String,Bucket> keysToBucket;
    private final Bucket head;
    private final Bucket tail;

    public AllOne() {
        keysToBucket = new HashMap<>();
        head = new Bucket(0);
        tail = new Bucket(0);
        head.next = tail;
        tail.prev = head;
    }

    public void inc(String key) {
        Bucket currBucket = keysToBucket.getOrDefault(key, head);
        Bucket nextBucket = currBucket.next;
        if (nextBucket.count != currBucket.count + 1) {
            nextBucket = new Bucket(currBucket.count + 1);
            currBucket.insertAfter(nextBucket);
        } 
        nextBucket.keys.add(key);
        removeKeyFromBucket(currBucket, key);
        keysToBucket.put(key, nextBucket);
    }

    public void dec(String key) {
        Bucket currBucket = keysToBucket.get(key), prevBucket = currBucket.prev;
        if (prevBucket.count != currBucket.count - 1) {
            prevBucket = new Bucket(currBucket.count - 1);
            currBucket.prev.insertAfter(prevBucket);
        } 
        if (currBucket.count != 1) {prevBucket.keys.add(key);}
        removeKeyFromBucket(currBucket, key);
        keysToBucket.put(key, prevBucket);
    }

    public String getMaxKey() {
        if (tail.prev == head) {return "";}
        return tail.prev.keys.iterator().next();
    }

    public String getMinKey() {
        if (head.next == tail) {return "";}
        return head.next.keys.iterator().next();
    }

    private void deleteBucket(Bucket bucket) {
        Bucket prev = bucket.prev, next = bucket.next;
        prev.next = next;
        next.prev = prev;
        bucket.next = null;
        bucket.prev = null;
    }

    private void removeKeyFromBucket(Bucket bucket, String key) {
        if (bucket.count > 0) {
            bucket.keys.remove(key);
            if (bucket.keys.isEmpty()) {deleteBucket(bucket);}
        }
    }
}

/**
 * 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();
 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贫道绝缘子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值