1. 程式人生 > >【系統設計】432. 全 O(1) 的數據結構

【系統設計】432. 全 O(1) 的數據結構

++ inf map 核心數 structure 是否為空 節點 tor lse

題目:

使用棧實現隊列的下列操作:

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

【系統設計】432. 全 O(1) 的數據結構