福哥答案2020-09-18:

方法:哈希表 + 双向链表。
时间复杂度:对于 put 和 get 都是 O(1)。
空间复杂度:O(capacity),因为哈希表和双向链表最多存储 capacity+1 个元素。

代码用go语言编写,代码如下:

package test40_lru

import (
"fmt"
"testing"
) /*
哈希表 + 双向链表
时间复杂度:对于 put 和 get 都是 O(1)O(1)。
空间复杂度:O(capacity),因为哈希表和双向链表最多存储 capacity+1 个元素。
*/
//https://leetcode-cn.com/problems/lru-cache/solution/lruhuan-cun-ji-zhi-by-leetcode-solution/
//go test -v -test.run TestLru
func TestLru(t *testing.T) {
cache := NewLRUCache(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 } type LRUCache struct {
size int
capacity int
cache map[int]*DLinkedNode
head, tail *DLinkedNode
} type DLinkedNode struct {
key, value int
prev, next *DLinkedNode
} func NewDLinkedNode(key, value int) *DLinkedNode {
return &DLinkedNode{
key: key,
value: value,
}
} func NewLRUCache(capacity int) LRUCache {
l := LRUCache{
cache: map[int]*DLinkedNode{},
head: NewDLinkedNode(0, 0),
tail: NewDLinkedNode(0, 0),
capacity: capacity,
}
l.head.next = l.tail
l.tail.prev = l.head
return l
} //获取元素
func (f *LRUCache) Get(key int) int {
//如果缓存里未找到元素
if _, ok := f.cache[key]; !ok {
fmt.Println(-1)
return -1
} //缓存里有元素
node := f.cache[key] //如果 key 存在,先通过哈希表定位,再移到头部
f.moveToHead(node)
fmt.Println(node.value)
return node.value
} //放入元素
func (f *LRUCache) Put(key int, value int) {
//如果缓存里没有元素
if _, ok := f.cache[key]; !ok {
node := NewDLinkedNode(key, value)
f.cache[key] = node
//放在头部
f.addToHead(node)
f.size++
//如果元素个数大于容量,需要删除元素
if f.size > f.capacity {
//删除链表尾部
removed := f.removeTail()
//删除map中的key
delete(f.cache, removed.key)
f.size--
}
} else { //缓存里有元素
//获取元素
node := f.cache[key]
//修改值
node.value = value
//移动到链表头
f.moveToHead(node)
}
} //添加到头节点
func (f *LRUCache) addToHead(node *DLinkedNode) {
node.prev = f.head
node.next = f.head.next
f.head.next.prev = node
f.head.next = node
} //删除节点
func (f *LRUCache) removeNode(node *DLinkedNode) {
node.prev.next = node.next
node.next.prev = node.prev
} //移动到头节点
func (f *LRUCache) moveToHead(node *DLinkedNode) {
f.removeNode(node)
f.addToHead(node)
} //删除尾部
func (f *LRUCache) removeTail() *DLinkedNode {
node := f.tail.prev
f.removeNode(node)
return node
}

执行结果如下:

2020-09-18:LRU手撸,说下时间复杂度和空间复杂度。的更多相关文章

  1. php手撸轻量级开发(一)

    聊聊本文内容 之前讲过php简单的内容,但是原生永远是不够看的,这次用框架做一些功能性的事情. 但是公司用自己的框架不能拿出来,用了用一些流行的框架比如tp,larveral之类的感觉太重,CI也不顺 ...

  2. 99%的程序员都在用Lombok,原理竟然这么简单?我也手撸了一个!|建议收藏!!!

    罗曼罗兰说过:世界上只有一种英雄主义,就是看清生活的真相之后依然热爱生活. 对于 Lombok 我相信大部分人都不陌生,但对于它的实现原理以及缺点却鲜为人知,而本文将会从 Lombok 的原理出发,手 ...

  3. Django框架:1、手撸web框架、Django框架简介、安装与使用和小白必会三板斧

    Django框架 目录 Django框架 一.Django推导流程 1.纯手撸web框架 2.基于wsgire模块 3.代码封装优化 4.动静态网页 5.jinja2模块 6.前端.后端.数据库三者联 ...

  4. [转]如何解决:Android中 Error generating final archive: Debug Certificate expired on 10/09/18 16:30 的错误

    本文转自:http://www.cnblogs.com/yyangblog/archive/2011/01/07/1929657.html 问题概述: 在导入一个app后提示如下错误: “Error ...

  5. php手撸轻量级开发(三)composer小白入门

    composer介绍 composer是php的一个依赖管理工具,在项目中声明所依赖的外部工具库,会自动安装这些工具库及所依赖的库文件. 对我等初阶工程狮来说,就是拉别人的代码,用别人的库,一个进阶版 ...

  6. 使用Java Socket手撸一个http服务器

    原文连接:使用Java Socket手撸一个http服务器 作为一个java后端,提供http服务可以说是基本技能之一了,但是你真的了解http协议么?你知道知道如何手撸一个http服务器么?tomc ...

  7. 康少带你手撸orm

    orm 什么是orm? 对象关系映射: 一个类映射成一张数据库的表 类的对象映射成数据库中的一条条数据 对象点数据映射成数据库某条记录的某个值 优点:不会写sql语句的程序员也可以很6的操作sql语句 ...

  8. .NET手撸2048小游戏

    .NET手撸2048小游戏 2048是一款益智小游戏,得益于其规则简单,又和2的倍数有关,因此广为人知,特别是广受程序员的喜爱. 本文将再次使用我自制的"准游戏引擎"FlysEng ...

  9. .NET手撸绘制TypeScript类图——下篇

    .NET手撸绘制TypeScript类图--下篇 在上篇的文章中,我们介绍了如何使用.NET解析TypeScript,这篇将介绍如何使用代码将类图渲染出来. 注:以防有人错过了,上篇链接如下:http ...

  10. 使用wsgiref手撸web框架

    模板 前言 要说到应用程序,就不得不提的就是cs架构和BS架构 所谓的cs架构就是client端和server端,就像我们的电脑上的qq,微信等应用程序 bs架构就是浏览器端和server端,我们不需 ...

随机推荐

  1. pandas加速读取数据记录csv大文件处理

    def readf(file): t0 = time.time() data=pd.read_csv(file,low_memory=False,encoding='gbk' #,nrows=100 ...

  2. ffmpeg+nginx+hls(低延迟)

    先看一下我参考的原文实现: 实现方案 https://zhuanlan.zhihu.com/p/87225094 流媒体服务器环境搭建 https://blog.csdn.net/impingo/ar ...

  3. 不同目录下npm run 报错

    不同目录下npm 报错sh: webpack: command not found npm ERR! file sh npm ERR! code ELIFECYCLE npm ERR! errno E ...

  4. 如何利用Apifox通过签名计算及数据加解密进行用户认证接口测试?

    用户注册场景:输入签名数据signature,appId,13位时间戳timestamp,6位随机数nonce,merchantId(非必填,本次不填)的请求参数发送给服务器,服务器返回响应数值后,校 ...

  5. vsftpd配置FTP服务器(Centos7.x安装)

    安装配置 1. 安装vsftpd 检查是否安装了vsftpd # rpm -qa | grep vsftpdvsftpd-2.2.2-24.el6.x86_64 如果有展示则已经安装,不需要重新安装 ...

  6. Dash 2.9.0版本重磅新功能一览

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master 大家好我是费老师,就在昨晚,Dash框架发布了其2.9.0版本更新,在一众更新 ...

  7. 【读书笔记】排列研究-置换角度(分解为Products Of Cycles) 含GroupExploer使用

    upd 2020-08-06 23:11完成了最初稿 目录 定义 开胃菜 entrée 群论角度 应用:几何变换 当然要从第一类斯特林数的角度来考虑一下 一个排列的type定义 排旗公式 应用-共轭排 ...

  8. linux使用汇总

    linux使用汇总 Linux的目录结构 没有逻辑磁盘分区(C盘.D盘...) 是一棵树形结构,根目录是/ 根目录下边有几个文件夹,需要我们了解: /etc:配置文件所在的文件夹.比如:安装JDK,配 ...

  9. Django笔记六之外键ForeignKey介绍

    这一篇笔记介绍 Django 系统 model 的外键处理,ForeignKey 以及相应的处理方法. 这是一种一对多的字段类型,表示两张表之间的关联关系. 本篇笔记的目录如下: on_delete ...

  10. 为自己的博客添加2D虚拟人物

    2020-05-29 在自己申请完并获得了属于自己的博客后,我突然想着为自己的博客添砖加瓦,记起了之前看别人博客时,其充满独具个性,特立独行的风格,让我十分羡慕,最近看到了一个博客风格很有趣,其有趣之 ...