Design - 146. LRU Cache
- LRU Cache
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and put
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value)
- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
The cache is initialized with a positive capacity.
Follow up: Could you do both operations in O(1) time complexity?
Example:
LRUCache cache = new LRUCache( 2 /* capacity */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
思路:
题目要求实现一个LRU Cache,提供get和put方法,时间复杂度都控制在O(1),get操作要求时间复杂度为O(1),说明肯定有一个hash的结构用来查找,put方法也是O(1)可以使用链表,这里使用双向链表,实现删除最后一个元素和把元素移动到链表头。对于链表类题目,最好的就是使用dummy节点,这样可以避免很多空针或者断链的情况发生。
代码:
go:
type LRUCache struct {
size int
capacity int
head *Node
tail *Node
m map[int]*Node
}
type Node struct {
key int
val int
prev *Node
next *Node
}
func Constructor(capacity int) LRUCache {
var lru = LRUCache{
capacity:capacity,
head: &Node{},
tail: &Node{},
m:make(map[int]*Node),
}
lru.head.next = lru.tail
lru.tail.prev = lru.head
return lru
}
func (this *LRUCache) Get(key int) int {
target, ok := this.m[key]
if !ok {
return -1
} else {
// moveToHead
this.moveToHead(target)
}
return target.val
}
func (this *LRUCache) Put(key int, value int) {
if target, ok := this.m[key]; ok {
// 更新target节点的值,然后把当前节点移动到链表头
target.val = value
this.moveToHead(target)
} else {
// 新生成一个节点,添加到链表头
node := &Node{key:key, val:value}
if this.size == this.capacity{
this.removeTail()
}
this.addToHead(node)
}
}
// 删除最后一个数据节点
func (this *LRUCache) removeTail() {
if len(this.m) == 0 {
return
}
delete(this.m, this.tail.prev.key)
this.size--
// remove tail
this.tail.prev.prev.next = this.tail
this.tail.prev = this.tail.prev.prev
}
// 从链表头添加新节点
func (this *LRUCache) addToHead(node *Node) {
temp := this.head.next
this.head.next = node
node.prev = this.head
node.next = temp
temp.prev = node
this.m[node.key]=node
this.size++
}
// 把节点移动到链表头
func (this *LRUCache) moveToHead(node *Node) {
// 把node摘出来
node.prev.next = node.next
node.next.prev = node.prev
this.size--
// 再放到链表头
this.addToHead(node)
}
/**
* Your LRUCache object will be instantiated and called as such:
* obj := Constructor(capacity);
* param_1 := obj.Get(key);
* obj.Put(key,value);
*/
- ReactJs和React Native的那些事
- Linux学习-文件排序和FASTA文件操作
- Bash漏洞再次演进:缓冲区溢出导致远程任意命令执行
- Pandas,让Python像R一样处理数据,但快
- ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示
- 最小生成树-Prim算法和Kruskal算法
- Bash漏洞批量检测工具与修复方案
- 组合模式
- 用Fiddler在Android上抓包(Http+https)
- Architecture Components ViewModel的控制。
- React Native之AppRegistry模块
- 揭秘:如何分分钟黑掉你的eBay账号
- C++初始化列表
- React Native调试心得
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- linux系统运维企业常见面试题集合(一)
- python第二十九课——文件读写(写数据的操作)
- python第二十九课——文件读写(复制文件)
- python第三十课--异常(异常处理定义格式和常见类型)
- python第三十课--异常(finally讲解)
- python第三十课--异常(else讲解)
- Linux系统——shell脚本编程基础介绍
- python第三十课--异常(raise关键字)
- python第三十课--异常(异常对象传递过程)
- python第三十课--异常(with as操作)
- linux系统运维企业常见面试题集合(二)
- Linux系统Shell编程—企业生产案例(一)
- python第三十一课--递归(1.简单递归函数的定义和使用)
- python第三十一课--递归(2.遍历某个路径下面的所有内容)
- python第三十一课--递归(3.递归的弊端)