zoukankan      html  css  js  c++  java
  • 【系统设计】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();
     */
  • 相关阅读:
    模型绑定
    Asp.Net MVC基础
    Entity Framework 6.x介绍
    IE内核发送ajax请求时不会将url中的参数编码
    .NET使用OpenSSL生成的pem密钥文件[1024位]
    简单测试nginx1.90做TCP协议负载均衡的功能
    《图解TCP/IP》读书笔记
    使用wireshark抓包分析浏览器无法建立WebSocket连接的问题(server为Alchemy WebSockets组件)
    wireshark常用的过滤器设置
    通过监控线程状态来保证socket服务器的稳定运行
  • 原文地址:https://www.cnblogs.com/mikemeng/p/8998266.html
Copyright © 2011-2022 走看看