【系統設計】432. 全 O(1) 的數據結構
阿新 • • 發佈:2018-05-06
++ 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) 的數據結構