「 【华为OD机试真题 Go语言实现】481、文件缓存系统 | 机试真题+思路参考+代码解析(C卷)」2024年6月29日

【华为OD机试真题 C语言】481、文件缓存系统 | 机试真题+思路参考+代码解析(C卷)

一、题目


 

🎃题目描述
请设计一个文件缓存系统,该文件缓存系统可以指定缓存的最大值(单位为字节)
 文件缓存系统有两种操作:
 1、存储文件(put)
 2、读取文件(get)
 操作命令为:
 1、put fileName fileSize
 2、get fileName
 存储文件是把文件放入文件缓存系统中;
 读取文件是从文件缓存系统中访问已存在,如果文件不存在,则不作任何操作。
 当缓存空间不足以存放新的文件时,根据规则删除文件,直到剩余空间满足新的文件大小位置,再存放新文件。
 具体的删除规则为:
 文件访问过后,会更新文件的最近访问时间和总的访问次数,当缓存不够时,按照第一优先顺序为访问次数从少到多,第二顺序为时间从老到新的方式来删除文件。
 🎃输入输出
输入
 第一行为缓存最大值 m(整数,取值范围为 0 < m ≤ 52428800)
 第二行为文件操作序列个数 n(0 ≤ n ≤ 300000)
 从第三行起为文件操作序列,每个序列单独一行,文件操作定义为:op file_name file_size
输出
 输出当前文件缓存中的文件名列表,文件名用英文逗号分隔,按字典顺序排序,如:a,c ;如果文件缓存中没有文件,则输出NONE
注意:
 1、如果新文件的文件名和文件缓存中已有的文件名相同,则不会放在缓存中
 2、新的文件第一次存入到文件缓存中时,文件的总访问次数不会变化,文件的最近访问时间会更新到最新时间
 3、每次文件访问后,总访问次数加1,最近访问时间更新到最新时间
 4、任何两个文件的最近访问时间不会重复
 5、文件名不会为空,均为小写字母,最大长度为10
 6、缓存空间不足时,不能存放新文件
 7、每个文件大小都是大于 0 的整数
🎃样例1
输入
50
6
put a 10
put b 20
get a
get a
get b
put c 30


输出
a,c
🎃样例2
输入
50
1
get file


输出
NONE

二、思路参考 

典型的LFU实现。 

三、代码参考


type file struct {
	name       string // max to 10 low case letters
	size       int
	frequency  int // access frequency
	accessDate time.Time
	index      int // the index of item in the heap
}

// PQ is a priority queue implements heap.Interface and holding files.
type PQ []*file

func (pq PQ) Len() int {
	return len(pq)
}

func (pq PQ) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
	pq[i].index = i
	pq[j].index = j
}

func (pq PQ) Less(i, j int) bool {
	if pq[i].frequency == pq[j].frequency {
		return pq[i].accessDate.Before(pq[j].accessDate)
	}
	return pq[i].frequency < pq[j].frequency
}

func (pq *PQ) Push(x any) {
	n := len(*pq)
	file := x.(*file)
	file.index = n
	file.accessDate = time.Now()
	*pq = append(*pq, file)

}

func (pq *PQ) Pop() any {
	old := *pq
	n := len(old)
	file := old[n-1]
	file.index = -1
	*pq = old[0 : n-1]
	return file
}

func (pq *PQ) update(f *file) {
	f.frequency++
	f.accessDate = time.Now()
	heap.Fix(pq, f.index)
}

type FileCache struct {
	// mapping from file name to *file
	m           map[string]*file
	pq          PQ
	capSize     int
	currentSize int
	fileCount   int
	accessDate  time.Time
}

func NewFileCache(capacity int) *FileCache {
	return &FileCache{
		m: make(map[string]*file),
		// 如果写pq: make([]*file, 8) 则表示cap len都是8,会有8个空元素,切记slice的小坑
		pq:      make([]*file, 0, 8),
		capSize: capacity,
	}
}

func (c *FileCache) GetFile(name string) {
	f, ok := c.m[name]
	if ok {
		c.pq.update(f)
	}

}

func (c *FileCache) PutFile(name string, size int) {
	if c.capSize < 0 {
		return
	}
	_, ok := c.m[name]
	if ok {
		// 文件存在,不做任何操作
		return
	}
	f := &file{
		name: name,
		size: size,
	}
	// 如果容量不足,evict一些文件
	if c.currentSize+size > c.capSize {
		c.evictFiles(size)
	}

	// 将文件存入,更新FileCache字段
	heap.Push(&c.pq, f)
	c.m[name] = f
	c.fileCount++
	c.currentSize += size
}

func (c *FileCache) evictFiles(reqSize int) {
	for c.currentSize+reqSize > c.capSize && c.fileCount > 0 {
		f := heap.Pop(&c.pq).(*file)
		c.currentSize -= f.size
		delete(c.m, f.name)
		c.fileCount--
	}
}

type ByName struct {
	PQ
}

func (by ByName) Less(i, j int) bool {
	return by.PQ[i].name < by.PQ[j].name
}

func (c *FileCache) Print() {
	if c.fileCount == 0 {
		fmt.Println("None")
	}
	sort.Sort(ByName{c.pq})
	for _, f := range c.pq {
		fmt.Printf("%s,", f.name)
	}
	fmt.Println()
	heap.Init(&c.pq)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值