1. 程式人生 > >【LeetCode】146. LRU快取機制 結題報告 (C++)

【LeetCode】146. LRU快取機制 結題報告 (C++)

題目描述:

運用你所掌握的資料結構,設計和實現一個  LRU (最近最少使用) 快取機制。它應該支援以下操作: 獲取資料 get 和 寫入資料 put 。

獲取資料 get(key) - 如果金鑰 (key) 存在於快取中,則獲取金鑰的值(總是正數),否則返回 -1。
寫入資料 put(key, value) - 如果金鑰不存在,則寫入其資料值。當快取容量達到上限時,它應該在寫入新資料之前刪除最近最少使用的資料值,從而為新的資料值留出空間。

進階:

你是否可以在 O(1) 時間複雜度內完成這兩種操作?

示例:

LRUCache cache = new LRUCache( 2 /* 快取容量 */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回  1
cache.put(3, 3);    // 該操作會使得金鑰 2 作廢
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 該操作會使得金鑰 1 作廢
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回  3
cache.get(4);       // 返回  4

解題方案:

新題型,屬於C++設計的題型,需要自己去定義很多變量了。

自己寫的程式碼,但是花費了過多的時間:

class LRUCache {
public:
    LRUCache(int capacity):size(capacity) {}
    
    int get(int key) {
        auto it = hash.find(key);
        if(it == hash.end())
            return -1;
        put(key, hash[key]);
        return hash[key];
    }
    
    void put(int key, int value) {
        auto it = find(cache.begin(), cache.end(), key);
        if(it != cache.end()){
            cache.erase(it);
            cache.push_back(key);
            hash[key] = value;
        }
        else if(cache.size() == size){
            hash.erase(cache.front());
            cache.pop_front();
            cache.push_back(key);
            hash.insert(pair<int, int>(key, value));
        }
        else{
            cache.push_back(key);
            hash.insert(pair<int, int>(key, value));
        }
    }

private:
    int size;
    map<int, int> hash;
    list<int> cache;
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

最終答案給出的時間開銷最小的程式碼:

static int x = []()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(NULL);
    return 0;
}();

struct Node
{
    int key;
    int val;
    Node* left;
    Node* right;
    
    Node(int k, int v): key(k), val(v), left(NULL), right(NULL) {}
};

class LRUCache {
public:
    LRUCache(int capacity) {
        
        mCapacity = 0;
        mStored = 0;
        
        head = NULL;
        tail = NULL;
        
        if (capacity > 0)
        {
            mCapacity = capacity;
            mData.assign(capacity, Node(0, 0));
        }
    }
    
    int get(int key) {
        auto it = mDict.find(key);
        if (it == mDict.end())
        {
            return -1;
        }
        
        moveToTail(it->second);
        
        return tail->val;
    }
    
    void put(int key, int value) {
        
        if (mCapacity <= 0)
        {
            return;
        }
        
        auto it = mDict.find(key);
        if (it != mDict.end())
        {
            // 已存在快取中的key,更新其val,將其移動到隊尾即可
            it->second->val = value;
            
            moveToTail(it->second);
            
            return;
        }
        
        if (mStored < mCapacity)
        {
            // 快取還未放滿
            Node* p = &mData[mStored];
            
            p->key = key;
            p->val = value;
            
            if (mStored == 0)
            {
                head = p;
                tail = p;
            }
            else
            {
                tail->right = p;
                p->left = tail;
                p->right = NULL;
                tail = p;
            }
            
            mDict.insert({key, p});
            
            mStored++;    
        }
        else
        {
            // 快取已滿,清除最久未使用的快取值
            Node* p = head;
            
            head = head->right;
            
            if (head != NULL)
            {
                head->left = NULL;
            }
            
            mDict.erase(p->key);
            
            p->key = key;
            p->val = value;
            
            tail->right = p;
            p->left = tail;
            p->right = NULL;
            tail = p;
            
            mDict.insert({key, p});
        }
    }
private:
    unordered_map<int, Node*> mDict;

    Node* head;
    Node* tail;
    
    vector<Node> mData;
    
    int mCapacity;
    int mStored;
    
    void moveToTail(Node* cur)
    {
        if (cur == tail)
        {
            return;
        }
        
        auto nl = cur->left;
        auto nr = cur->right;
            
        if (nl == NULL)
        {
            head = nr;
        }
        else
        {
            nl->right = nr;
        }
            
        nr->left = nl;
            
        tail->right = cur;
        cur->left = tail;
        cur->right = NULL;    
        
        tail = cur;
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

相關推薦

LeetCode146. LRU快取機制 報告 (C++)

題目描述: 運用你所掌握的資料結構,設計和實現一個  LRU (最近最少使用) 快取機制。它應該支援以下操作: 獲取資料 get 和 寫入資料 put 。 獲取資料 get(key) - 如果金鑰 (key) 存在於快取中,則獲取金鑰的值(總是正數),否則返回 -1。

LeetCode166. 分數到小數 報告 (C++)

原題地址:https://leetcode-cn.com/problems/fraction-to-recurring-decimal/description/ 題目描述: 給定兩個整數,分別表示分數的分子 numerator 和分母 denominator,以字串形式返回小數。 如果小

LeetCode165. 比較版本號 報告 (C++)

原題地址:https://leetcode-cn.com/problems/compare-version-numbers/description/ 題目描述: 比較兩個版本號 version1 和 version2。 如果 version1 > version2 返回 1,如果 ve

LeetCode164. 最大間距 報告 (C++)

原題地址:https://leetcode-cn.com/problems/maximum-gap/description/ 題目描述: 給定一個無序的陣列,找出陣列在排序之後,相鄰元素之間最大的差值。 如果陣列元素個數小於 2,則返回 0。 示例 1: 輸入: [3,6,9,1

LeetCode93. 復原IP地址 報告 (C++)

原題地址:https://leetcode-cn.com/problems/restore-ip-addresses/description/ 題目描述: 給定一個只包含數字的字串,復原它並返回所有可能的 IP 地址格式。 示例: 輸入: "25525511135" 輸出: ["25

LeetCode85. 最大矩形 報告 (C++)

原題地址:https://leetcode-cn.com/problems/maximal-rectangle/description/ 題目描述: 給定一個僅包含 0 和 1 的二維二進位制矩陣,找出只包含 1 的最大矩形,並返回其面積。 示例: 輸入: [   ["1"

LeetCode140. 單詞拆分 II報告 (C++)

原題地址:https://leetcode-cn.com/problems/word-break-ii/description/ 題目描述: 給定一個非空字串 s 和一個包含非空單詞列表的字典 wordDict,在字串中增加空格來構建一個句子,使得句子中所有的單詞都在詞典中。返回所有這些可能

LeetCode221. 最大正方形 報告 (C++)

原題地址:https://leetcode-cn.com/problems/maximal-square/submissions/ 題目描述: 在一個由 0 和 1 組成的二維矩陣內,找到只包含 1 的最大正方形,並返回其面積。 示例: 輸入:  1 0 1 0 0 1

LeetCode218. 天際線問題 報告 (C++)

原題地址:https://leetcode-cn.com/problems/the-skyline-problem/ 題目描述: 城市的天際線是從遠處觀看該城市中所有建築物形成的輪廓的外部輪廓。現在,假設您獲得了城市風光照片(圖A)上顯示的所有建築物的位置和高度,請編寫一個程式以輸出由這些建

LeetCode216. 組合總和 III 報告 (C++)

原題地址:https://leetcode-cn.com/problems/combination-sum-iii/submissions/ 題目描述: 找出所有相加之和為 n 的 k 個數的組合。組合中只允許含有 1 - 9 的正整數,並且每種組合中不存在重複的數字。 說明: 所有

LeetCode169. 求眾數 報告 (C++)

原題地址:https://leetcode-cn.com/problems/majority-element/submissions/ 題目描述: 給定一個大小為 n 的陣列,找到其中的眾數。眾數是指在陣列中出現次數大於 ⌊ n/2 ⌋ 的元素。 你可以假設陣列是非空的,並且給定的陣列總

LeetCode127. 單詞接龍 報告 (C++)

題目描述: 給定兩個單詞(beginWord 和 endWord)和一個字典,找到從 beginWord 到 endWord 的最短轉換序列的長度。轉換需遵循如下規則: 每次轉換隻能改變一個字母。 轉換過程中的中間單詞必須是字典中的單詞。 說明: 如果不存在這樣的轉

LeetCode299. 猜數字遊戲 報告 (C++)

原題地址:https://leetcode-cn.com/problems/bulls-and-cows/submissions/ 題目描述: 你正在和你的朋友玩 猜數字(Bulls and Cows)遊戲:你寫下一個數字讓你的朋友猜。每次他猜測後,你給他一個提示,告訴他有多少位數字和確切位

LeetCode40. 組合總和 II 報告 (C++)

題目描述: 給定一個數組 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。 candidates 中的每個數字在每個組合中只能使用一次。 說明: 所有數字(包括目標數)都是正整數。

LeetCode9. 迴文數 報告 (C++)

判斷一個整數是否是迴文數。迴文數是指正序(從左向右)和倒序(從右向左)讀都是一樣的整數。示例 1:輸入: 121 輸出: true 示例 2:輸入: -121 輸出: false 解釋: 從左向右讀, 為 -121 。 從右向左讀, 為 121- 。因此它不是一個迴文數。 示例 3:輸入: 10 輸出: fa

LeetCode 146. LRU快取機制(java實現)

參考解答 總結:這道題主要要知道選取何種資料結構並且在 O(1) 時間複雜度內完成這兩種操作? O(1) 的get方法肯定要用到HashMap() LinkedList(雙向連結串列)可以以O(1)時間複雜度,很方便地實現資料的插入和刪除 所以,將兩個資料結構聯合使用,Ha

leetcode146.(Hard)LRU Cache

解題思路: 用map來記錄資料 用list陣列更新資料的使用情況 提交程式碼: class LRUCache { Map<Integer,Integer> map=new HashMap<>(); List<Integer> histor

[Leetcode]146.LRU快取機制

Leetcode難題,題目為: 運用你所掌握的資料結構,設計和實現一個  LRU (最近最少使用) 快取機制。它應該支援以下操作: 獲取資料 get 和 寫入資料 put 。 獲取資料 get(key) - 如果金鑰 (key

LeetCode154. 尋找旋轉排序陣列中的最小值 II 報告 (C++)

原題地址:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii/description/ 題目描述: 假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。 ( 例如,陣列 [0,1,2,4,5,

LeetCode153. 尋找旋轉排序陣列中的最小值 報告 (C++)

原題地址:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/description/ 題目描述: 假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。 ( 例如,陣列 [0,1,2,4,5,6,7