leetcode146:LRU缓存

题目链接

leetcode

题目描述

请你设计并实现一个满足 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) 的平均时间复杂度运行。

C++ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <iostream>
#include <vector>
#include <unordered_map>
#include <list>
using namespace std;

/*
哈希表 + 双向链表

时间复杂度:O(1)
get 操作 O(1),因为哈希表可以快速定位结点,而移动结点到头部也是 O(1) 操作。
put 操作 O(1),因为哈希表和链表操作都是 O(1) 复杂度。
空间复杂度:O(capacity)
其中 capacity 是缓存的最大容量。
哈希表占用空间最多为 O(capacity),链表占用空间最多为 O(capacity) 的空间。
*/
class LRUCache {
public:
LRUCache(int capacity) {
this->capacity = capacity;
head = new Node(), tail = new Node();
head->next = tail, tail->prev = head;
}

int get(int key) {
// key 不存在
if (!cache.count(key)) {
return -1;
}
// key 存在
Node* p = cache[key];
removeNode(p);
addNode(p);
return p->val;
}

void put(int key, int value) {
// key 不存在
if (!cache.count(key)) {
// 缓存已满
if (cache.size() == capacity) {
Node* p = tail->prev;
removeNode(p);
cache.erase(p->key);
delete p;
// p = nullptr;
}
// 缓存不满
Node* p = new Node(key, value);
addNode(p);
cache[key] = p;
} else {
// key 存在
Node* p = cache[key];
p->val = value;
removeNode(p);
addNode(p);
}
}

private:
struct Node {
int key, val;
Node *prev, *next;
Node() : key(-1), val(-1), prev(nullptr), next(nullptr) {}
Node(int k, int v) : key(k), val(v), prev(nullptr), next(nullptr) {}
};
// 双向链表
Node *head, *tail;
// 哈希表
unordered_map<int, Node*> cache;
// 缓存容量
int capacity;

// 添加一个节点到链表的头部
void addNode(Node* p) {
p->prev = head;
p->next = head->next;
head->next->prev = p;
head->next = p;
}

// 从链表中删除一个节点
void removeNode(Node* p) {
p->next->prev = p->prev;
p->prev->next = p->next;
}
};

// 辅助函数:打印数组
void printArray(const vector<string>& nums) {
cout << "[";
for (size_t i = 0; i < nums.size(); i++) {
cout << nums[i];
if (i != nums.size() - 1) cout << ",";
}
cout << "]";
}

void printArray(const vector<int>& nums) {
cout << "[";
for (size_t i = 0; i < nums.size(); i++) {
if (nums[i] == NULL) {
cout << "null";
} else {
cout << nums[i];
}
if (i != nums.size() - 1) cout << ",";
}
cout << "]";
}

// 辅助函数:打印二维数组
void printArray(const vector<vector<int>>& nums) {
cout << "[";
for (size_t i = 0; i < nums.size(); i++) {
cout << "[";
for (size_t j = 0; j < nums[i].size(); j++) {
cout << nums[i][j];
if (j != nums[i].size() - 1) cout << ",";
}
cout << "]";
if (i != nums.size() - 1) cout << ",";
}
cout << "]";
}

int main() {
LRUCache* obj = new LRUCache(2);
vector<string> operations = {"LRUCache","put","put","get","put","get","put","get","get","get"};
vector<vector<int>> params = {{2},{1,1},{2,2},{1},{3,3},{2},{4,4},{1},{3},{4}};
vector<int> output;

for (int i = 0; i < operations.size(); i++) {
string op = operations[i];
if (op == "LRUCache") {
output.push_back(NULL); // 表示无返回值
} else if (op == "put") {
obj->put(params[i][0], params[i][1]);
output.push_back(NULL);
} else if (op == "get") {
int res = obj->get(params[i][0]);
output.push_back(res);
}
}

cout << "Input: " << endl;
printArray(operations);
cout << endl;
printArray(params);
cout << endl;
cout << "Output: " << endl;
printArray(output);
cout << endl;

delete obj;

return 0;
}

leetcode146:LRU缓存
https://lcf163.github.io/2024/04/11/leetcode146:LRU缓存/
作者
乘风的小站
发布于
2024年4月11日
许可协议