阿里云笔试题整理

前言

昨天参加了阿里云的笔试,笔试是单独给我发了一个链接,不像是统一的笔试,两个小时做两个题也是我没有想到的,最后还是没有做完。所以就想着来整理以下这两个题目,下面就开始了。

LRU缓存

题目

  • 第一题:
  • 实现一个 LRU 缓存,支持指定缓存大小,支持 get 和 put 操作。使用频率越低的数据放在越后面,若缓存满了,删除最后面的数据。(语言不限)
  • 输入:操作序列,包括 get 和 put 操作。
  • 输出:根据 get 操作返回对应的值,put 操作无输出。
  • 要求:时间复杂度为 O(1)。需要考虑编程习惯,包括但不限于可读性、可维护性、命名规范、代码风格等。

分析

  1. 这个题是力扣第147题,如果我们要实现时间复杂度为O(1)的要求,而且要满足使用频率越低的数据放在最后,也就是说当我们put一个数据之后,首先需要查询这个数据是否存在,如果存在还需要把这个数据放到最前面,其次是get方法,也需要我们查找到一个数据,再返回。
  2. 我们能够想到的查询方法基本上不会有O(1)的存在,所以这里我们需要借助多个数据结构,比如用一个HashMap记录每一个节点的id和节点,用一个双向链表记录节点之间的相对位置。每次get节点,就用这个id来获取节点信息,可以直接在哈希映射(Hashmap)里面查找,这个复杂度为O(1),找到之后获取对应的节点,然后输出节点的value。
  3. 在实现get功能的时候,我们也要知道怎么定义一个节点,也就是说节点类里面有什么信息,就像定义二叉树的节点一样,双向链表的节点如何定义呢?那就看以下代码:
class DlinkedNode{
   
	int key;
	int value;
	DlinkedNode prev;
	DlinkedNode next;
	DlinkedNode(){
   }
	DlinkedNode(int key_,int value_){
   
		key = key_;
		value = value_;
	}
}

由此能够构建一个双向链表。

代码

public class LRUCache {
   
	// 正是因为链表节点有向前和向后的指针,所以当我们在HashMap中找到他的时候,我们同样能够在双向链表中找到他的位置
    class DLinkedNode {
   
        int key;
        int value;
        DLinkedNode prev;
        DLinkedNode next;
        public DLinkedNode() {
   }
        public DLinkedNode(int _key, int _value) {
   key = _key; value = _value;}
    }
	// 用HashMap来存储节点和id, 一个LRUCache就包括以下内容,首先有一个HashMap
	// 其次就是双向链表所需要的头指针与尾指针,再就是Cache的容量和目前已有的数据个数
    private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();
    private int size;
    private int capacity;
    private DLinkedNode head, tail;
	//初始化的时候就得将各个变量都初始化,而且形成双向链表
    public LRUCache(int capacity) {
   
        this.size = 0;
        this.capacity = capacity;
        // 使用伪头部和伪尾部节点
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
   
        DLinkedNode node = cache.get(key);
        if (node == null) {
   
            
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>