【系统设计】432. 全 O(1) 的数据结构

题目:

使用栈实现队列的下列操作:

push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。
注意:

你只能使用标准的栈操作-- 也就是只有push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque (双端队列) 来模拟一个栈,只要是标准的栈操作即可。
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。

本题解题思路:

思考过程中考虑到可以用两个map来解决该问题,但发现比较麻烦,后自己写了一个解决方案:

核心数据结构:

struct DoubleListNode{
    void * val;
    DoubleListNode * pre;
    DoubleListNode * next;
    DoubleListNode(void * x):val(x){
        pre = NULL;
        next = NULL;
    }
};

struct StrToken{
    int counter;
    set<string> strs;
};

 用一个排序的双向链表来存储所有的key和key的计数,数列的计数从小到大。

如果返回最小计数的key,则返回队列中的头元素,如果返回最大计数的key,则返回队列的最末位的元素;

 

插入元素:

如果发现该key已经存在map中,则找到该节点,将该key插入到其计算加1的链表节点中去,同时更新map映射;如果发现该key不存在,则将该key插入到计算为1的节点中去,同时更新map映射。

删除元素:

如果发现该key已经存在map中,则找到该节点,将该key插入到其计算减一的链表节点中去同时更新MAP映射。

 返回最大值:

由于链表是按照计算的大小排列的,返回链表中的最后端的元素即可。

返回最小值:

 由于链表是按照计算的大小排列的,返回链表中的最前端的元素即可。

源代码如下,leetcode执行时间为40ms

struct DoubleListNode{
    void * val;
    DoubleListNode * pre;
    DoubleListNode * next;
    DoubleListNode(void * x):val(x){
        pre = NULL;
        next = NULL;
    }
};

struct StrToken{
    int counter;
    set<string> strs;
};

class DoubleLinkList{
public:
    DoubleLinkList(){
        head = new DoubleListNode(NULL);
        tail = new DoubleListNode(NULL);
        head->next = tail;
        tail->pre = head;
        cnt = 0;
    }
    
    bool insertHead(DoubleListNode * node){
        if(NULL == node || NULL == head){
            return false;
        }
        
        node->next = head->next;
        node->pre = head;
        head->next->pre = node;
        head->next = node;
        cnt++;
        
        return true;
    }
    
    bool insertTail(DoubleListNode * node){
        if(NULL == node || NULL == tail){
            return false;
        }
        
        node->next = tail;
        node->pre = tail->pre;
        tail->pre->next = node;
        tail->pre = node;
        cnt++;
        
        return true;
    }
    
    DoubleListNode * getHead(){
        return this->head;
    }
    
    DoubleListNode * getTail(){
        return this->tail;
    }
    
    DoubleListNode * getNext(const DoubleListNode * target){
        if(NULL == target){
            return NULL;
        }
        
        return target->next;
    }
    
    DoubleListNode * getPrev(const DoubleListNode * target){
        if(NULL == target){
            return NULL;
        }
        
        return target->pre;
    }
    
    bool isHead(const DoubleListNode * target){
        if(head == target){
            return true;
        }else{
            return false;
        }
    }
    
    bool isTail(const DoubleListNode * target){
        if(tail == target){
            return true;
        }else{
            return false;
        }
    }
    
    bool deleteTarget(DoubleListNode * node){
        if(NULL == node || node == head || node == tail){
            return false;
        }
        
        if(!node->pre || !node->next){
            return false;
        }
        
        node->pre->next = node->next;
        node->next->pre = node->pre;
        
        node->next = NULL;
        node->pre = NULL;
        if(node->val){
            delete node->val;
            node->val = NULL;
        }
        
        delete node;
        node = NULL;
        
        return true;
    }
    
    
    bool insertBefore(DoubleListNode * target,DoubleListNode * node){
        if(NULL == target || NULL == node){
            return false;
        }
        
        node->pre = target->pre;
        node->next = target;
        target->pre->next = node;
        target->pre = node;
        cnt++;
        
        return true;
    }
    
    bool insertAfter(DoubleListNode * target,DoubleListNode * node){
        if(NULL == target || NULL == node){
            return false;
        }
        
        node->pre = target;
        node->next = target->next;
        target->next->pre = node;
        target->next = node;
        cnt++;
        
        return true;
    }
    
    int length(){
        return cnt;
    }
    
    bool isEmpty(){
        if(head->next == tail){
            return true;
        }else{
            return false;
        }
    }
    
private:
    struct DoubleListNode * head;
    struct DoubleListNode * tail;
    int cnt;
};
 


class AllOne {
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(keyMap.find(key) == keyMap.end()){
            /*we wiil insert the first node*/
            DoubleListNode * head = keyList.getHead();
            DoubleListNode * next = keyList.getNext(head);
            StrToken * toke = (StrToken *)(next->val);
            
            /*we will add a new node in to the linklist*/
            if(keyList.isEmpty() || (toke != NULL && toke->counter > 1)){
                StrToken  * newToke = new StrToken();
                newToke->counter = 1;
                newToke->strs.insert(key);
                DoubleListNode * newNode = new DoubleListNode(newToke);
                keyList.insertHead(newNode);
                keyMap[key] = newNode;
            }else{/*we add the key in to the token*/
                if( NULL != toke && toke->counter == 1){
                    toke->strs.insert(key);
                    keyMap[key] = next;
                }
            }        
        }else{
            map<string,DoubleListNode *>::iterator it = keyMap.find(key);
            DoubleListNode * node =  it->second;
            StrToken * toke = (StrToken *)(node->val);
            toke->strs.erase(key);
            DoubleListNode * next =  keyList.getNext(node);
            StrToken * nextToke = NULL;
            if(next != keyList.getTail()){
                nextToke = (StrToken *)(next->val);
            }
            
            if(next == keyList.getTail() ||
               (nextToke!=NULL && nextToke->counter > (toke->counter+1))){
                StrToken  * newToke = new StrToken();
                newToke->counter = toke->counter+1;
                newToke->strs.insert(key);
                DoubleListNode * newNode = new DoubleListNode(newToke);
                keyList.insertAfter(node,newNode);
                keyMap[key] = newNode;
            }else{
                if(nextToke){
                    nextToke->strs.insert(key);
                    keyMap[key] = next;
                }  
            }
            
            if(toke->strs.empty()){
                keyList.deleteTarget(node);
            }
        }
        
        //debug();
    }
    
    /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
    void dec(string key) {
        if(keyMap.find(key) == keyMap.end()){
            return;
        }
        
        map<string,DoubleListNode *>::iterator it = keyMap.find(key);
        DoubleListNode * node =  it->second;
        StrToken * toke = (StrToken *)(node->val);
        toke->strs.erase(key);
        DoubleListNode * prev =  keyList.getPrev(node);
        StrToken * prevToke = NULL;
        if(prev != keyList.getHead()){
            prevToke = (StrToken *)(prev->val);
        }
        
        
        if(toke->counter > 1){
            if(prev == keyList.getHead() || 
               (prevToke!=NULL && prevToke->counter < (toke->counter - 1))){
                StrToken  * newToke = new StrToken();
                newToke->counter = toke->counter - 1;
                newToke->strs.insert(key);
                DoubleListNode * newNode = new DoubleListNode(newToke);
                keyList.insertBefore(node,newNode);
                keyMap[key] = newNode;
            }else{
                if(prevToke){
                    prevToke->strs.insert(key);
                    keyMap[key] = prev;
                }
            }
        }else{
            keyMap.erase(key);
        }
        
       if(toke->strs.empty()){
            keyList.deleteTarget(node);
        }
        
        //debug();
    }
    
    
    /** Returns one of the keys with maximal value. */
    string getMaxKey() {
        string res;
        if(keyList.isEmpty()){
            return res;
        }
        
        DoubleListNode * node = keyList.getPrev(keyList.getTail());
        StrToken * toke = (StrToken *)(node->val);
        return *(toke->strs.begin());
    }
    
    /** Returns one of the keys with Minimal value. */
    string getMinKey() {
        string res;
        if(keyList.isEmpty()){
            return res;
        }
        
        DoubleListNode * node = keyList.getNext(keyList.getHead());
        StrToken * toke = (StrToken *)(node->val);
        return *(toke->strs.begin());
    }
    
    void debug(){
        cout<<endl;
        DoubleListNode * node = keyList.getNext(keyList.getHead());
        for(;node!=keyList.getTail();node = keyList.getNext(node)){
            StrToken * toke = (StrToken *)(node->val);
            cout<<"cnt:"<<toke->counter<<endl;
            set<string>::iterator it = toke->strs.begin();
            for(;it!=toke->strs.end();++it){
                cout<<*it<<" ";
            }
            cout<<endl;
        }
    }
    
private:
    map<string,DoubleListNode *> keyMap;
    DoubleLinkList  keyList;
};

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

猜你喜欢

转载自www.cnblogs.com/mikemeng/p/8998266.html