美文网首页
Leetcode Design Tag

Leetcode Design Tag

作者: 一只小鹿鹿鹿 | 来源:发表于2018-03-26 04:58 被阅读0次

    Design

    // LRU Cache
    // 99 ms
    class LRUCache {
    private:
        int capacity;
        int size;
        unordered_map<int, int> cache;
        unordered_map<int, list<int>::iterator> position;
        list<int> visited;
        
    public:
        LRUCache(int capacity) {
            this->capacity = capacity;
            this->size = 0;
        }
        
        int get(int key) {
            if (cache.find(key) != cache.end()) {
                visit(key);
                return cache[key];
            }
            return -1;
        }
        
        void put(int key, int value) {
            if (cache.find(key) != cache.end()) {
                cache[key] = value;
                visit(key);
            } else {
                if (size == capacity) 
                    invalidate();
                cache[key] = value;
                visited.push_front(key);
                position[key] = visited.begin();
                size++;
            }
        }
        
        void visit(int key) {
            list<int>::iterator iter = position[key];
            visited.erase(iter);
            visited.push_front(key);
            position[key] = visited.begin();
        }
        
        void invalidate() {
            int key = visited.back();
            visited.pop_back();
            cache.erase(key);
            position.erase(key);
            size--;
        }
    };
    // 86 ms
    class LRUCache {
    private:
        struct CacheNode {
            int key;
            int value;
            CacheNode(int k, int v) : key(k), value(v) {}
        };
        
    public:
        LRUCache(int capacity) {
            this->capacity = capacity;
        }
        
        int get(int key) {
            if (cacheMap.find(key) != cacheMap.end()) {
                cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
                cacheMap[key] = cacheList.begin();
                return cacheMap[key]->value;
            } else {
                return -1;
            }
        }
        
        void put(int key, int value) {
            if (capacity == 0)
                return;
            if (cacheMap.find(key) != cacheMap.end()) {
                cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
                cacheMap[key] = cacheList.begin();
                cacheMap[key]->value = value;
            } else {
                if (cacheMap.size() == capacity) {
                    cacheMap.erase(cacheList.back().key);
                    cacheList.pop_back();
                }
                cacheList.emplace_front(CacheNode(key, value)); // emplace_front比push_front快
                cacheMap[key] = cacheList.begin();
            }
        }
    
    private:
        int capacity;
        list<CacheNode> cacheList;
        unordered_map<int, list<CacheNode>::iterator> cacheMap;   
    };
    
    // LFU Cache
    // 99ms
    class LFUCache {
    private:
        struct FrequencyListNode {
            int frequency;
            list<int> visited;
            FrequencyListNode(int f) : frequency(f) {}
        };
        
        int capacity;
        int size;
        unordered_map<int, int> cache;
        list<FrequencyListNode> frequencyList;
        unordered_map<int, list<FrequencyListNode>::iterator> index1;
        unordered_map<int, list<int>::iterator> index2;
        
    public:
        LFUCache(int capacity) {
            this->capacity = capacity;
            this->size = 0;
        }
        
        int get(int key) {
            if (cache.find(key) != cache.end()) {
                visit(key);
                return cache[key];
            }
            return -1;
        }
        
        void put(int key, int value) {
            if (capacity == 0)
                return;
            if (cache.find(key) != cache.end()) {
                cache[key] = value;
                visit(key);
            } else {
                if (size == capacity) 
                    invalidate();
                cache[key] = value;
                if (frequencyList.empty() || (frequencyList.front()).frequency > 1)
                    frequencyList.push_front(FrequencyListNode(1));
                (frequencyList.front()).visited.push_front(key);
                index1[key] = frequencyList.begin();
                index2[key] = (frequencyList.begin())->visited.begin();
                size++;
            }
        }
        
        void visit(int key) {
            list<FrequencyListNode>::iterator iter1 = index1[key];
            list<int>::iterator iter2 = index2[key];
            int frequency = iter1->frequency;
            iter1->visited.erase(iter2);
            if (iter1->visited.empty())
                iter1 = frequencyList.erase(iter1); // Important!: erase后重新赋给iter1
            else
                iter1++;
            if (iter1 == frequencyList.end() || iter1->frequency > frequency + 1)
                iter1 = frequencyList.insert(iter1, FrequencyListNode(frequency + 1)); // Important!: insert后重新赋给iter1
            iter1->visited.push_front(key);
            index1[key] = iter1;
            index2[key] = iter1->visited.begin();
        }
        
        void invalidate() {
            int key = (frequencyList.begin())->visited.back();
            (frequencyList.begin())->visited.pop_back();
            if ((frequencyList.begin())->visited.empty())
                frequencyList.pop_front();
            cache.erase(key);
            index1.erase(key);
            index2.erase(key);
            size--;
        }
    };
    // 168 ms
    class LFUCache {
    private:
        struct CacheNode {
            int key;
            int value;
            CacheNode(int k, int v) : key(k), value(v) {}
        };
        
        struct CacheBucket {
            int frequency;
            list<CacheNode> cacheList;
            unordered_map<int, list<CacheNode>::iterator> cacheMap;  // map<key, cacheNode> (second-layer index)
            CacheBucket(int f) : frequency(f) {}
        };
        
    public:
        LFUCache(int capacity) {
            this->capacity = capacity;
        }
        
        int get(int key) {
            if (cacheMap.find(key) != cacheMap.end()) {
                list<CacheBucket>::iterator bucket = cacheMap[key];
                list<CacheNode>::iterator node = bucket->cacheMap[key];
                int value = node->value;
                inc(bucket, key, value);
                return value;
            } else {
                return -1;
            }
        }
        
        void put(int key, int value) {
            if (capacity == 0) return;
            if (cacheMap.find(key) != cacheMap.end()) {
                list<CacheBucket>::iterator bucket = cacheMap[key];
                inc(bucket, key, value);
            } else {
                if (cacheMap.size() == capacity) {
                    cache.front().cacheMap.erase(cache.front().cacheList.back().key);
                    cacheMap.erase(cache.front().cacheList.back().key);
                    cache.front().cacheList.pop_back();
                    if (cache.front().cacheMap.empty())
                        cache.pop_front();
                }
                if (cache.empty() || cache.front().frequency > 1)
                    cache.insert(cache.begin(), CacheBucket(1));
                cache.front().cacheList.push_front(CacheNode(key, value));
                cache.front().cacheMap[key] = cache.front().cacheList.begin();
                cacheMap[key] = cache.begin();
            }
        }
        
        void inc(list<CacheBucket>::iterator &bucket, int key, int value) { // frequency + 1
            int frequency = bucket->frequency;
            bucket->cacheList.erase(bucket->cacheMap[key]);
            bucket->cacheMap.erase(key);
            
            if (bucket->cacheMap.empty())
                bucket = cache.erase(bucket);
            else
                bucket++;
            if (bucket == cache.end() || bucket->frequency > frequency + 1) {
                cache.insert(bucket, CacheBucket(frequency + 1));
                bucket--;
            }
            bucket->cacheList.push_front(CacheNode(key, value));
            bucket->cacheMap[key] = bucket->cacheList.begin();
            cacheMap[key] = bucket;
        }
    private:
        int capacity;
        list<CacheBucket> cache;
        unordered_map<int, list<CacheBucket>::iterator> cacheMap;  // map<key, cacheBucket> (first-layer index)
    };
    
    // Find Median from Data Stream
    // 考虑两个优先队列(最大最小堆)
    class MedianFinder {
    public:
        /** initialize your data structure here. */
        MedianFinder() {}
        
        void addNum(int num) {
            if (maxpq.empty() || num <= maxpq.top()) {
                maxpq.push(num);
                if (maxpq.size() > minpq.size() + 1) {
                    int median = maxpq.top();
                    maxpq.pop();
                    minpq.push(median);
                }
            } else {
                minpq.push(num);
                if (maxpq.size() < minpq.size()) {
                    int median = minpq.top();
                    minpq.pop();
                    maxpq.push(median);
                }
            }        
        }
        
        double findMedian() {
            if (maxpq.size() == minpq.size())
                return ((double)maxpq.top() + (double)minpq.top()) / 2;
            else
                return maxpq.top();
        }
    private:
        priority_queue<int> maxpq; // has smaller half of the numbers
        priority_queue<int, vector<int>, greater<int>> minpq; // has larger half of the numbers
        // Ensure that maxpq.size() == minpq.size() or maxpq.size() == minpq.size() + 1
    };
    
    // Insert Delete GetRandom O(1)
    class RandomizedSet {
    public:
        /** Initialize your data structure here. */
        RandomizedSet() {
            
        }
        
        /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
        bool insert(int val) {
            if (pos.find(val) != pos.end())
                return false;
            elements.push_back(val);
            pos[val] = elements.size() - 1;
            return true;
        }
        
        /** Removes a value from the set. Returns true if the set contained the specified element. */
        bool remove(int val) {
            if (pos.find(val) == pos.end())
                return false;
            if (pos[val] < elements.size() - 1) {
                int replace_val = elements.back();
                pos[replace_val] = pos[val];
                elements[pos[val]] = replace_val;
            }
            pos.erase(val);
            elements.pop_back();
            return true;
        }
        
        /** Get a random element from the set. */
        int getRandom() {
            return elements[rand() % elements.size()];
        }
    private:
        vector<int> elements;
        unordered_map<int, int> pos;
    };
    
    // Insert Delete GetRandom O(1) - Duplicates allowed
    // 56 ms
    class RandomizedCollection {
    private:
        struct CacheNode {
            int frequency;
            list<int> pos;
            unordered_map<int, list<int>::iterator> posCache;
            CacheNode() {} // Important!: 要保留默认构造函数
            CacheNode(int f, int p) {
                frequency = f;
                pos.push_back(p);
                posCache[p] = --pos.end(); // Important!: 没有pos.end() - 1,pos.end()--也是错的
            }
            void inc(int p) {
                frequency++;
                pos.push_back(p);
                posCache[p] = --pos.end();
            }
            int dec() {
                frequency--;
                int p = pos.back();
                pos.pop_back();
                posCache.erase(p);
                return p;
            }
            void update(int p, int q) {
                pos.erase(posCache[p]);
                posCache.erase(p);
                pos.push_back(q);
                posCache[q] = --pos.end();
            }
        };
        
    public:
        /** Initialize your data structure here. */
        RandomizedCollection() {
            size = 0;
        }
        
        /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
        bool insert(int val) {
            elements.push_back(val);
            if (cache.find(val) != cache.end()) {
                cache[val].inc(size++);
                return false;
            } else {
                cache[val] = CacheNode(1, size++); // 因为这里会先调用默认构造函数,再调用operator =
                return true;
            }
        }
        
        /** Removes a value from the collection. Returns true if the collection contained the specified element. */
        bool remove(int val) {
            if (cache.find(val) == cache.end())
                return false;
            int p = cache[val].dec();
            if (cache[val].frequency == 0)
                cache.erase(val);
            if (p < size - 1) {
                int replace_val = elements[size - 1];
                elements[p] = replace_val;
                cache[replace_val].update(size - 1, p);
            }
            elements.pop_back();
            size--;
            return true;
        }
        
        /** Get a random element from the collection. */
        int getRandom() {
            return elements[rand() % size];
        }
    
    private:
        unordered_map<int, CacheNode> cache;
        vector<int> elements;
        int size;
    };
    
    // All O`one Data Structure
    class AllOne {
    public:
        struct CacheNode {
            int value;
            list<string> keys;
            CacheNode() {}
            CacheNode(int v, string key) : value(v) { keys.push_back(key); }
        };
        /** 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 (index1.find(key) == index1.end()) {
                if (cache.empty() || cache.front().value > 1)
                    cache.push_front(CacheNode(1, key));
                else
                    cache.front().keys.push_front(key);
                index1[key] = cache.begin();
                index2[key] = cache.front().keys.begin();
            } else {
                list<CacheNode>::iterator iter1 = index1[key];
                list<string>::iterator iter2 = index2[key];
                int value = iter1->value;
                iter1->keys.erase(iter2);
                if (iter1->keys.empty())
                    iter1 = cache.erase(iter1);
                else
                    iter1++;
                if (iter1 == cache.end() || iter1->value > value + 1)
                    iter1 = cache.insert(iter1, CacheNode(value + 1, key));
                else
                    iter1->keys.push_front(key);
                index1[key] = iter1;
                index2[key] = iter1->keys.begin();
            }
        }
        
        /** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
        void dec(string key) {
            if (index1.find(key) != index1.end()) {
                list<CacheNode>::iterator iter1 = index1[key];
                list<string>::iterator iter2 = index2[key];
                int value = iter1->value;
                iter1->keys.erase(iter2);
                if (iter1->keys.empty())
                    iter1 = cache.erase(iter1);
                if (value == 1) {
                    index1.erase(key);
                    index2.erase(key);
                    return;
                }
                if (iter1 == cache.begin()) {
                    cache.push_front(CacheNode(value - 1, key));
                    iter1 = cache.begin();
                } else if ((--iter1)->value < value - 1) {
                    iter1 = cache.insert(++iter1, CacheNode(value - 1, key));
                } else {
                    iter1->keys.push_front(key);
                }
                index1[key] = iter1;
                index2[key] = iter1->keys.begin();
            }
        }
        
        /** Returns one of the keys with maximal value. */
        string getMaxKey() {
            return cache.back().keys.front();
        }
        
        /** Returns one of the keys with Minimal value. */
        string getMinKey() {
            return cache.front().keys.front();
        }
    private:
        list<CacheNode> cache;
        unordered_map<string, list<CacheNode>::iterator> index1;
        unordered_map<string, list<string>::iterator> index2;
    };
    
    // Peeking Iterator
    // Since Iterator has a copy constructor, we can just use it
    // Below is the interface for Iterator, which is already defined for you.
    // **DO NOT** modify the interface for Iterator.
    class Iterator {
        struct Data;
        Data* data;
    public:
        Iterator(const vector<int>& nums);
        Iterator(const Iterator& iter);
        virtual ~Iterator();
        // Returns the next element in the iteration.
        int next();
        // Returns true if the iteration has more elements.
        bool hasNext() const;
    };
    
    class PeekingIterator : public Iterator {
    public:
        PeekingIterator(const vector<int>& nums) : Iterator(nums) {
            // Initialize any member here.
            // **DO NOT** save a copy of nums and manipulate it directly.
            // You should only use the Iterator interface methods.
        }
    
        // Returns the next element in the iteration without advancing the iterator.
        int peek() {
            return Iterator(*this).next();
        }
    
        // hasNext() and next() should behave the same as in the Iterator interface.
        // Override them if needed.
        int next() {
            return Iterator::next();
        }
    
        bool hasNext() const {
            return Iterator::hasNext();
        }
    };
    
    // Min Stack
    class MinStack {
    private:
        struct StackNode {
            int value;
            int min;
            StackNode *next;
            StackNode(int value, int min, StackNode *next) : value(value), min(min), next(next) {}
        };
        StackNode *head;
    public:
        /** initialize your data structure here. */
        MinStack() {
            head = NULL;
        }
        void push(int x) {
            if (head == NULL)
                head = new StackNode(x, x, NULL);
            else {
                head = new StackNode(x, min(x, getMin()), head);
            }
        }
        void pop() {
            if (head) {
                StackNode *newhead = head->next;
                free(head);
                head = newhead;
            }
        }
        int top() {
            if (head)
                return head->value;
        }
        int getMin() {
            if (head)
                return head->min;
        }
    };
    class MinStack {
    private:
        stack<int> s1;
        stack<int> s2;
    public:
        void push(int x) {
            s1.push(x);
            if (s2.empty() || x <= getMin())  s2.push(x);       
        }
        void pop() {
            if (s1.top() == getMin())  s2.pop();
            s1.pop();
        }
        int top() {
            return s1.top();
        }
        int getMin() {
            return s2.top();
        }
    };
    
    // Implement Queue using Stacks
    class MyQueue {
    public:
        /** Initialize your data structure here. */
        MyQueue() {   
        }
        /** Push element x to the back of queue. */
        void push(int x) {
            input.push(x);
        }
        /** Removes the element from in front of queue and returns that element. */
        int pop() {
            int result = peek();
            output.pop();
            return result;
        }
        /** Get the front element. */
        int peek() {
            if (output.empty())
                transfer();
            return output.top();
        }
        /** Returns whether the queue is empty. */
        bool empty() {
            return input.empty() && output.empty();
        }
        void transfer() {
            while (!input.empty()) {
                output.push(input.top());
                input.pop();
            }
        }
    private:
        stack<int> input, output;
    };
    
    // Implement Stack using Queues
    class MyStack {
    public:
        /** Initialize your data structure here. */
        MyStack() { 
        }
        /** Push element x onto stack. */
        void push(int x) {
            q.push(x);
        }
        /** Removes the element on top of the stack and returns that element. */
        int pop() {
            queue<int> p;
            while (q.size() > 1) {
                p.push(q.front());
                q.pop();
            }
            int result = q.front();
            q = p;
            return result;
        }
        /** Get the top element. */
        int top() {
            int result;
            queue<int> p;
            while (!q.empty()) {
                result = q.front();
                p.push(q.front());
                q.pop();
            }
            q = p;
            return result;
        }
        /** Returns whether the stack is empty. */
        bool empty() {
            return q.empty();
        }
    private:
        queue<int> q;
    };
    
    // Flatten Nested List Iterator
    class NestedIterator {
    public:
        NestedIterator(vector<NestedInteger> &nestedList) {
            initialize(nestedList);
            pos = 0;
        }
    
        int next() {
            return vec[pos++];
        }
    
        bool hasNext() {
            return pos != vec.size();
        }
    private:
        vector<int> vec;
        int pos;
        void initialize(vector<NestedInteger> &nestedList) {
            for (NestedInteger i : nestedList) {
                if (i.isInteger())
                    vec.push_back(i.getInteger());
                else
                    initialize(i.getList());
            }
        }
    };
    class NestedIterator {
    public:
        NestedIterator(vector<NestedInteger> &nestedList) {
            if (!nestedList.empty()) {
                s.push(make_pair(nestedList.begin(), nestedList.end()));
                adjust();
            }
        }
    
        int next() {
            vector<NestedInteger>::iterator ib = s.top().first, ie = s.top().second, iter;
            s.pop();
            int res = ib->getInteger();
            ib++;
            if (ib != ie)
                s.push(make_pair(ib, ie));
            adjust();
            return res;
        }
    
        bool hasNext() {
            return !s.empty();
        }
    private:
        stack<pair<vector<NestedInteger>::iterator, vector<NestedInteger>::iterator>> s;
        void adjust() {
            while (!s.empty() && !s.top().first->isInteger()) {
                vector<NestedInteger>::iterator ib = s.top().first, ie = s.top().second, iter;
                s.pop();
                iter = ib;
                ib++;
                if (ib != ie)
                    s.push(make_pair(ib, ie));
                if (!iter->getList().empty())
                    s.push(make_pair(iter->getList().begin(), iter->getList().end()));
            }
        }
    };
    class NestedIterator {
    public:
        NestedIterator(vector<NestedInteger> &nestedList) {
            s.push(make_pair(nestedList.begin(), nestedList.end()));
            adjust();
        }
    
        int next() {
            int res = s.top().first->getInteger();
            s.top().first++;
            adjust();
            return res;
        }
    
        bool hasNext() {
            return !s.empty();
        }
    private:
        stack<pair<vector<NestedInteger>::iterator, vector<NestedInteger>::iterator>> s;
        void adjust() {
            while (!s.empty()) {
                if (s.top().first == s.top().second) {
                    s.pop();
                } else {
                    if (s.top().first->isInteger())
                        break;
                    vector<NestedInteger>::iterator iter = s.top().first;
                    s.top().first++;
                    s.push(make_pair(iter->getList().begin(), iter->getList().end()));
                }
            }
        }
    };
    
    // Binary Search Tree Iterator
    class BSTIterator {
    public:
        BSTIterator(TreeNode *root) {
            TreeNode *p = root;
            while (p) {
                s.push(p);
                p = p->left;
            }
        }
        /** @return whether we have a next smallest number */
        bool hasNext() {
            return !s.empty();
        }
        /** @return the next smallest number */
        int next() {
            int res = s.top()->val;
            TreeNode *p = s.top()->right;
            if (p) {
                while (p) {
                    s.push(p);
                    p = p->left;
                }
            } else {
                p = s.top();
                s.pop();
                while (!s.empty() && p == s.top()->right) {
                    p = s.top();
                    s.pop();
                }
            }
            return res;
        }
    private:
        stack<TreeNode*> s;
    };
    class BSTIterator {
    public:
        BSTIterator(TreeNode *root) {
            TreeNode *p = root;
            while (p) {
                s.push(p);
                p = p->left;
            }
        }
        /** @return whether we have a next smallest number */
        bool hasNext() {
            return !s.empty();
        }
        /** @return the next smallest number */
        int next() {
            int res = s.top()->val;
            TreeNode *p = s.top()->right;
            s.pop();
            while (p) {
                s.push(p);
                p = p->left;
            }
            return res;
        }
    private:
        stack<TreeNode*> s;
    };
    
    // Flatten 2D Vector
    class Vector2D {
    public:
        Vector2D(vector<vector<int>>& vec2d) {
            x = vec2d.begin();
            end = vec2d.end();
        }
        int next() {
            return (*x)[y++];
        }
        bool hasNext() {
            while (x != end && y == (*x).size()) {
                ++x; 
                y = 0;
            }
            return x != end;
        }
    private:
        vector<vector<int>>::iterator x, end;
        int y = 0;
    };
    

    相关文章

      网友评论

          本文标题:Leetcode Design Tag

          本文链接:https://www.haomeiwen.com/subject/napsqftx.html