2020-09-18:LRU手撸,说下时间复杂度和空间复杂度。
福哥答案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手撸,说下时间复杂度和空间复杂度。的更多相关文章
- php手撸轻量级开发(一)
聊聊本文内容 之前讲过php简单的内容,但是原生永远是不够看的,这次用框架做一些功能性的事情. 但是公司用自己的框架不能拿出来,用了用一些流行的框架比如tp,larveral之类的感觉太重,CI也不顺 ...
- 99%的程序员都在用Lombok,原理竟然这么简单?我也手撸了一个!|建议收藏!!!
罗曼罗兰说过:世界上只有一种英雄主义,就是看清生活的真相之后依然热爱生活. 对于 Lombok 我相信大部分人都不陌生,但对于它的实现原理以及缺点却鲜为人知,而本文将会从 Lombok 的原理出发,手 ...
- Django框架:1、手撸web框架、Django框架简介、安装与使用和小白必会三板斧
Django框架 目录 Django框架 一.Django推导流程 1.纯手撸web框架 2.基于wsgire模块 3.代码封装优化 4.动静态网页 5.jinja2模块 6.前端.后端.数据库三者联 ...
- [转]如何解决: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 ...
- php手撸轻量级开发(三)composer小白入门
composer介绍 composer是php的一个依赖管理工具,在项目中声明所依赖的外部工具库,会自动安装这些工具库及所依赖的库文件. 对我等初阶工程狮来说,就是拉别人的代码,用别人的库,一个进阶版 ...
- 使用Java Socket手撸一个http服务器
原文连接:使用Java Socket手撸一个http服务器 作为一个java后端,提供http服务可以说是基本技能之一了,但是你真的了解http协议么?你知道知道如何手撸一个http服务器么?tomc ...
- 康少带你手撸orm
orm 什么是orm? 对象关系映射: 一个类映射成一张数据库的表 类的对象映射成数据库中的一条条数据 对象点数据映射成数据库某条记录的某个值 优点:不会写sql语句的程序员也可以很6的操作sql语句 ...
- .NET手撸2048小游戏
.NET手撸2048小游戏 2048是一款益智小游戏,得益于其规则简单,又和2的倍数有关,因此广为人知,特别是广受程序员的喜爱. 本文将再次使用我自制的"准游戏引擎"FlysEng ...
- .NET手撸绘制TypeScript类图——下篇
.NET手撸绘制TypeScript类图--下篇 在上篇的文章中,我们介绍了如何使用.NET解析TypeScript,这篇将介绍如何使用代码将类图渲染出来. 注:以防有人错过了,上篇链接如下:http ...
- 使用wsgiref手撸web框架
模板 前言 要说到应用程序,就不得不提的就是cs架构和BS架构 所谓的cs架构就是client端和server端,就像我们的电脑上的qq,微信等应用程序 bs架构就是浏览器端和server端,我们不需 ...
随机推荐
- 记录下老dropbox的使用
32-bit: wget -O - "https://www.dropbox.com/download?plat=lnx.x86" | tar xzf - 64-bit: wget ...
- Qt非主线程显示窗口的简易思路
首发于我的个人博客:xie-kang.com 博客内有更多文章,欢迎大家访问 原文地址 Qt 在非主线程是无法显示UI窗口的,如果我们在其它线程中处理完数据,需要使用窗口展示,或者在其它线程需要使用到 ...
- 【chatQA】nvm包版本管理
如何使用nvm来管理不同版本的 Node.js,然后使用不同的 Node.js 版本来运行不同版本的 React 应用? 要使用 nvm 来管理不同版本的 Node.js,可以按照以下步骤进行操作: ...
- salesforce零基础学习(一百二十七)Custom Metadata Type 篇二
本篇参考: salesforce零基础学习(一百一十一)custom metadata type数据获取方式更新 https://developer.salesforce.com/docs/atlas ...
- MyBatisPlus-------id生成策略
不同的表对应不同的id生成策略 日志:自增 购物订单:特殊规则(FQ23324AK443) 外卖单:关联地区日期等信息( 10 04 20200314 34 91) 关系表:可省略id ....... ...
- Java面试——搜索
更多内容,前往 IT-BLOG 一.Elasticsearch了解多少 ElasticSearch 是一个基于 Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTfu ...
- PHP的序列化和反序列化
PHP序列化 什么是PHP序列化 serialize() //将一个对象转换成一个字符串 unserialize() //将字符串还原成一个对象 通过序列化与反序列化我们可以很方便的在PHP中进行对象 ...
- TypeScript 学习总结
TypeScript JavaScript 语言 面向对象编程语言 面向脚本编程 是否支持可选参数 支持 不支持 是否支持静态类型 支持 不支持 是否支持接口 支持 不支持 TS:是JS的超集,即对J ...
- iOS 深色模式适配
要求:iOS13.0以上 重点:需要所有界面进行适配,工作量巨大,需要从项目开始就进行适配:H5界面无法进行适配 实现方式:System Colors(常用).Semantic Colors(常用). ...
- STM32 HAL库学习(F407ZGT6) (1)-晶振/时钟树
时钟树(以F407为例) 对于 STM32F4 系列的芯片,正常工作的主频可以达到 168Mhz,但并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及RTC只需要几十Khz的时钟即可.同一个 ...