记录leetcode刷题

146. LRU缓存

题目描述

请你设计并实现一个满足 LRU (最近最少使用) 缓存约束的数据结构。实现LRUCache类:

  • LRUCache(int capacity):以正整数作为容量 capacity ,初始化 LRU 缓存
  • int get(int key) :如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value):如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过capacity ,则应该逐出最久未使用的关键字。
    函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/lru-cache

整体思路
  • 这道题目的整体思路就是使用哈希表 + 双向链表来实现,哈希表中存储key->val的映射,所有的节点按照双向链表来存储,方便进行插入删除。(当前可以使用c++提供的STL进行,也可以自己熟悉下这两者的工作方式,,虽然双向链表听起来可能很简单,但是真的动手去写,会有很多需要注意的地方,注意每个指针的指向,考虑全面)
  • get函数分析:
    主要的函数流程如下,其中将节点置于队列尾部要分情况讨论,分别是该节点在head、tail或者中间位置。
Created with Raphaël 2.3.0 get函数 map中存在? 将该节点置于队列尾部 返回map对应的节点的val 结束 返回-1 yes no
  • put函数分析
Created with Raphaël 2.3.0 put函数 map中存在? 更新val值 将该节点置于队列尾部 (同get中处理) 结束 size < capacity? 插入新的节点需要判断当前 个数,0时单独处理 取消head节点的map映射 以head节点作为新的节点,修改节 点信息建立新的map映射 将head置于队尾 yes no yes no
struct Node {
    int val;
    int key;
    Node* last;
    Node* next;
};

class LRUCache {
public:
    LRUCache(int capacity) {
        head = NULL;
        tail = head;
        size = 0;
        this->capacity = capacity;
    }
    
    int get(int key) {
        std::map<int, Node*>::iterator it = my_map.find(key);
        if (it != my_map.end()) {
            Node *tem_one = my_map[key];
            if (tem_one == head) { // 访问的是head
                head = tem_one->next;
                tail = tem_one;
            }
            else if (tem_one != tail){ // 访问的不是tail,即为中间的
                tem_one->last->next = tem_one->next;
                tem_one->next->last = tem_one->last;

                head->last = tem_one;
                tem_one->next = head;
                tail->next = tem_one;
                tem_one->last = tail;

                tail = tem_one;
            }
            return tem_one->val;
        }
        else {
            return -1;
        }
    }
    
    void put(int key, int value) {
        std::map<int, Node*>::iterator it = my_map.find(key);
        if (it != my_map.end()) { // 存在,置于队尾
            Node *tem_one = my_map[key];
            my_map[key]->val = value;
            if (tem_one == head) { // 访问的是head
                head = tem_one->next;
                tail = tem_one;
            }
            else if (tem_one != tail){ // 访问的不是tail,即为中间的
                tem_one->last->next = tem_one->next;
                tem_one->next->last = tem_one->last;

                head->last = tem_one;
                tem_one->next = head;
                tail->next = tem_one;
                tem_one->last = tail;

                tail = tem_one;
            }
        }
        else { // 不存在
            if (size < capacity) { // 还没有满
                Node* new_one = new Node;
                new_one->val = value;
                new_one->key = key;
                my_map[key] = new_one;
                size++;
                if (head == NULL) { // 还没有节点存在
                    head = new_one;
                    tail = head;
                    new_one->last = new_one;
                    new_one->next = new_one;
                }
                else { // 已经存在一个节点
                    new_one->last = tail;
                    new_one->next = head;
                    tail->next = new_one;
                    head->last = new_one;
                    tail = new_one;
                }
            }
            else { // 满了,删掉head,并将新的添加到队尾
                Node *tem_one = head;
                my_map.erase(tem_one->key);
                tem_one->key = key;
                tem_one->val = value;
                my_map[key] = tem_one;
                head = tem_one->next;
                tail = tem_one;
            }
        }
    }

private:
    Node* head;
    Node* tail;
    int size;
    int capacity;
    map<int, Node*> my_map;
};

103. 二叉树的锯齿形层序遍历

题目描述

给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

  • 整体思想比较简单,每次遍历时,将当前层的节点按照顺序保存下来,用来进行下一次遍历。同时将每层的节点val保存为一个vector,用来记录结果。
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<TreeNode*> left;
        vector<TreeNode*> right;
        vector<vector<int>> res;

        if (root == NULL) {return res;}
        res.push_back(vector<int>(1, root->val)); // push the first
        
        bool left_first = true;
        left.push_back(root);
        while (left.size() != 0 || right.size() != 0) {
            vector<int> tem_res; // 存储这一层的结果
            if (left_first) { // 从左向右
                int n = left.size();
                for (int i = 0; i < n; ++i) {
                    TreeNode* tem = left.back();
                    left.pop_back();
                    if (tem->right != NULL) {
                        tem_res.push_back(tem->right->val);
                        right.insert(right.begin(), tem->right);
                    }
                    if (tem->left != NULL) {
                        tem_res.push_back(tem->left->val);
                        right.insert(right.begin(), tem->left);
                    }
                }
            }
            else { // 从右向左
                int n = right.size();
                for (int i = 0; i < n; ++i) {
                    TreeNode* tem = right[0];
                    right.erase(right.begin());
                    if (tem->left != NULL) {
                        tem_res.push_back(tem->left->val);
                        left.push_back(tem->left);
                    }
                    if (tem->right != NULL) {
                        tem_res.push_back(tem->right->val);
                        left.push_back(tem->right);
                    }
                }
            }
            if (!tem_res.empty()) {
                res.push_back(tem_res);
            }
            left_first = !left_first;
        }
    
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值