20230517-Codetop

95 阅读2分钟

1、leetcode146 LRU缓存机制

思路:

  • 需要一个双向链表维护所有当前存在的节点,被新插入\修改\查询的节点要被移动到链表头。如果在节点内部维护一个时间戳,则每次操作都需要更新所有节点,不满足O1时间复杂度。
  • 插入新节点后size加一,如果此时size超过了capacity,则需要淘汰链表尾的节点以维持capacity。
  • 由于要求O1的读写,需要一个哈希表,以节点key值为key,以节点指针为value。
struct node{
    node* prev;
    node* next;
    int key;
    int value;
    node(): key(0), value(0), prev(nullptr), next(nullptr) {}
    node(int k, int v): key(k), value(v), prev(nullptr), next(nullptr) {}
};

class LRUCache {
public:
    LRUCache(int capacity): size(0), cap(capacity) {
        head = new node();
        tail = new node();
        head->next = tail;
        tail->prev = head;
    }
    
    int get(int key) {
        if(!map.count(key)) return -1;
        node* p = map[key];
        removeNode(p);
        addToHead(p);
        return p->value;
    }
    
    void put(int key, int value) {
        if(!map.count(key)){
            node* p = new node(key, value);
            addToHead(p);
            map.emplace(key, p);
            ++size;
            if(size > cap){
                node* q = tail->prev;
                removeNode(q);
                map.erase(q->key);
                delete q;
            }
        }
        else{
            node* p = map[key];
            p->value = value;
            removeNode(p);
            addToHead(p);
        }
    }
    void removeNode(node* p){
        p->next->prev = p->prev;
        p->prev->next = p->next;
    }

    void addToHead(node* p){
        p->next = head->next;
        p->prev = head;
        head->next->prev = p;
        head->next = p;
    }
private:
    unordered_map<int, node*> map;
    int size;
    int cap;
    node* head;
    node* tail;
};

2、leetcode3 无重复字符的最长子串

思路:

  • 注意是子串,不是子序列,因此非常适用于滑窗
  • 外层循环每次将右指针加一,内层循环检查当前窗口有没有右指针指向的字符,有则一直将左指针加一。
  • 每次外层循环更新答案最大值(内存循环不需要,因为内层循环必然是长度减小)
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_set<char> window;
        int ans = 0;
        for(int l = 0, r = 0; r < s.size(); ++r){
            while(l <= r && window.count(s[r])){
                window.erase(s[l]);
                ++l;
            }
            window.emplace(s[r]);
            ans = max(ans, r - l + 1);
        }
        return ans;
    }
};

今天先写这两道,说实话滑窗的常用模板都快忘了,调了半天。 不每天练真不行吧。