目录
- 350-两个数组的交集
- 283-移动零
- 1-两数之和
- 25-K 个一组翻转链表
- 581-最短无序连续子数组
- 合并区间
- 螺旋矩阵
- 数组中相加和为0的三元组
- 数组中出现次数超过一半的数字
- 字符串出现次数的TopK问题
- 206-反转链表
- 160-相交链表
- 19-删除链表的倒数第N个节点
- 21-合并两个有序链表
- 31-下一个排列
- 链表K位翻转
- 链表排序-归并算法
- 判断链表中是否有环
- 设计LRU缓存结构
- 两个链表的第一个公共结点
- 两个链表生成相加链表
- 合并N个有序链表
- 链表内指定区间反转
设计LRU缓存结构
访问量:1421
一、简介
设计LRU(最近最少使用)缓存结构,该结构在构造时确定大小,假设大小为 k ,并有如下两个功能
1. set(key, value):将记录(key, value)插入该结构
2. get(key):返回key对应的value值
提示:
1.某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的,然后都会刷新缓存。
2.当缓存的大小超过k时,移除最不经常使用的记录。
3.输入一个二维数组与k,二维数组每一维有2个或者3个数字,第1个数字为opt,第2,3个数字为key,value
若opt=1,接下来两个整数key, value,表示set(key, value)
若opt=2,接下来一个整数key,表示get(key),若key未出现过或已被移除,则返回-1
对于每个opt=2,输出一个答案
4.为了方便区分缓存里key与value,下面说明的缓存里key用""号包裹
要求:set和get操作复杂度均为 O(1)O(1)
二、具体实现
思路:利用双向链表+hash表,双向链表保留位置信息,确定哪些元素最近最少使用,hash表便于实现元素的快速查找。每次新增和查找,都将元素从链表中移动到首位。
type LruCache struct { Size int data map[int]*CacheNode firstNode *CacheNode lastNode *CacheNode } type CacheNode struct { k int v int next *CacheNode pre *CacheNode } func (l *LruCache) add(k, v int) { curNode, isOk := l.data[k] if !isOk { if len(l.data) >= l.Size { // 删除最后一个元素 l.delLast() } // 插入当前节点 curNode = &CacheNode{ k: k, v: v, } if l.firstNode != nil { curNode.next = l.firstNode l.firstNode.pre = curNode l.firstNode = curNode } else { l.firstNode = curNode l.lastNode = curNode } l.data[k] = curNode return } else { // 需要修改当前节点的值 curNode.v = v // 将 curNode调整到首位 l.chg2First(curNode) } } func (l *LruCache) get(k int) int { curNode, isOk := l.data[k] if isOk { l.chg2First(curNode) return curNode.v } return -1 } func (l *LruCache) chg2First(node *CacheNode) { // 如果已经是首位,直接返回 if l.firstNode == node { return } // 如果在末尾 if node == l.lastNode { // 将末尾改为 node前一个节点 nodePre := node.pre nodePre.next = nil l.lastNode = nodePre // node.pre = nil node.next = l.firstNode l.firstNode.pre = node l.firstNode = node return } // 如果在中间节点 parentNode := node.pre nextNode := node.next parentNode.next = nextNode nextNode.pre = parentNode node.next = l.firstNode node.pre = nil l.firstNode.pre = node l.firstNode = node } func (l *LruCache) delLast() { // 如果就剩一个元素 if len(l.data) == 1 { l.firstNode = nil l.lastNode = nil delete(l.data, l.firstNode.k) return } delete(l.data, l.lastNode.k) preNode := l.lastNode.pre l.lastNode = preNode preNode.next = nil } func LRU(operators [][]int, k int) []int { cache := &LruCache{ Size: k, data: make(map[int]*CacheNode), } rs := make([]int, 0) for _, item := range operators { if item[0] == 1 && len(item) >= 3 { // inset cache.add(item[1], item[2]) } else if item[0] == 2 && len(item) >=2 { // get rs = append(rs, cache.get(item[1])) } } return rs }
题目来源:牛客
本文为原创文章,请尊重辛勤劳动,如需转载,请保留本文地址
若您感觉本站文章不错,读后有收获,不妨赞助一下?
我要赞助