432. All O`one Data Structure

博客围绕All O(1)数据结构展开,介绍了Inc、Dec、GetMaxKey、GetMinKey等操作,要求时间复杂度为O(1)。采用按val划分key子集,用struct Bucket装{val, keys},bucket用list连接,用hash存key及所在bucket指针。还提及实现中的易错点,如iterator使用、特殊情况判断等。

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

432. All O`one Data Structure


Implement a data structure supporting the following operations:

Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty string.
Dec(Key) - If Key’s value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string.
GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string “”.
GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string “”.

Challenge: Perform all these in O(1) time complexity.

方法1:

discussion: https://leetcode.com/problems/all-oone-data-structure/discuss/91398/C%2B%2B-solution-with-comments

思路:

为了所有操作都是O(1),采用按照val把key划分成子集的结构,用一个struct Bucket来装{val, keys},bucket之间采用list的结构连接起来。这样在getmin/getmax时,可以直接取头节点/尾节点子集中任意key。为了能inc和dec也达到O(1),需要一个hash来存所有的key,并且能够按要求将list中的key移动到新的bucket,为此,hash中的value是key此时所在的bucket的指针。如果在增加/减小之后不存在对应的bucket,就需要在list中添加,耗时也是O(1)。将key加到新的bucket当中,并从之前的bucket中删除。此时如果之前的bucket变空,需要从list中删掉这个节点。

易错点

  1. iterator不可以+1,但是可以++。
  2. 要判断next == buckets.end(), 和bucket == buckets.begin()的特殊情况,否则会heap overflow。
  3. 删除时如果头节点的val = 1, 从这里删除不需要建立新bucket,但是仍然需要从hash中把对应的key删掉。
  4. *(buckets.rbegin() -> keys.begin()):要解指针
class AllOne {
private:
    struct Bucket {
        int val;
        unordered_set<string> keys;
    };
    list<Bucket> buckets;
    unordered_map<string, list<Bucket>::iterator> hash;
public:
    /** Initialize your data structure here. */
    AllOne() {
        
    }
    
    /** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
    void inc(string key) {
        if (!hash.count(key)) {
            buckets.insert(buckets.begin(), {0, {key}});
            hash[key] = buckets.begin();
        }
        
        auto next = hash[key], bucket = next++;
        // if end of the list, or not consecutive vals, construct a new bucket
        if (next == buckets.end() || next -> val > bucket -> val + 1) {
            next = buckets.insert(next, {bucket -> val + 1, {}});
        }
        next -> keys.insert(key);
        hash[key] = next;
        
        // remove key from the old bucket, if the bucket is empty, remove from the buckets list
        bucket -> keys.erase(key);
        if (bucket -> keys.empty()) {
            buckets.erase(bucket);
        }
    }
    
    /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
    void dec(string key) {
        if (!hash.count(key)) return;
        auto prev = hash[key], bucket = prev--;
        hash.erase(key);
        // if bucket -> val == 1, don't neet to create new prev bucket
        if (bucket -> val > 1){
            //  if no prev bucket or gap with prev bucket
            if (bucket == buckets.begin() || prev -> val < bucket -> val - 1) {
                prev = buckets.insert(bucket, {bucket -> val - 1, {}});
            }
            prev -> keys.insert(key);
            hash[key] = prev;
        }
       
        // remove key from the old bucket, if the bucket is empty, remove from the buckets list
        bucket -> keys.erase(key);
        if (bucket -> keys.empty()) {
            buckets.erase(bucket);
        }
    }
    
    /** Returns one of the keys with maximal value. */
    string getMaxKey() {
        return buckets.empty() ? "" : *(buckets.rbegin() -> keys.begin());
    }
    
    /** Returns one of the keys with Minimal value. */
    string getMinKey() {
        return buckets.empty() ? "" : *(buckets.begin() -> keys.begin());
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值