数据结构与算法---LRU缓存机制、会议室

LRU缓存机制

146. LRU缓存机制

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。

实现 LRUCache 类:

  • LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作?

提示:
1 <= capacity <= 3000
0 <= key <= 3000
0 <= value <= 104
最多调用 3 * 104 次 get 和 put


LRU:(Least Recently User)最近最少使用
LRUCache的常见实现方式是:哈希表+双向链表

为何是哈希表和双向链表?

由于put和get都要求在O(1)时间内完成,所以,哈希表是最好的选择

在这里插入图片描述
当调用get的时候:
如果通过key找到了value,那么会将该value插入到虚拟头结点的后面,这样,get调用过的数据,永远在前面
如果通过key没有找到value,则返回-1

当调用put的时候:
如果通过get(key),找到的value不为空,说明里面原来就有value,则更新value的值,由于调用了get方法,则该key放在虚拟头结点的后面
如果通过get(key),找到的value为空,说明目前LRU里面没有该value

如果此时容量满了,则删除虚拟尾节点指向的节点,然后将新的key-value插入到虚拟头节点的后面
如果此时容量没有满,则将新的key-value插入到虚拟头节点的后面

class LRUCache {
    //创建一个hashMap
    Map<Integer, Node> map;
    private int capacity;
    //虚拟头节点
    private Node first;
    //虚拟尾节点
    private Node last;

    public LRUCache(int capacity) {
        map = new HashMap<>(capacity);
        //将容量从局部变量变为成员变量,put方法里面要用到
        this.capacity = capacity;

        //初始化
        first = new Node();
        last = new Node();

        //一开始没有数据,头尾相连
        first.next = last;
        last.pre = first;
    }
    
    public int get(int key) {
        Node node = map.get(key);
        if(node == null) return -1;

        //访问该节点,将该节点放在虚拟头节点后面
        removeNode(node);
        insertBehindFirst(node);

        return node.value;
    }
    
    public void put(int key, int value) {
        //检查key是否存在
        Node node = map.get(key);
        if(node != null){//说明已经存在,现在要更新
            node.value = value;
            removeNode(node);
            insertBehindFirst(node);
        }else{//添加新值
            //放的时候,看看容量满了没有
            if(capacity == map.size()){//满了,直接替换旧的
                //淘汰最久没使用的
                map.remove(last.pre.key);
                removeNode(last.pre);
            }
            Node newNode = new Node(key, value);
            map.put(key, newNode);
            insertBehindFirst(newNode);
        }
    }

    private void removeNode(Node node){
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    private void insertBehindFirst(Node node){
        //node先与后面产生联系
        node.next = first.next;
        first.next.pre = node;
        node.pre = first;
        first.next = node;
    }

    private static class Node{
        public int key;
        public int value;
        public Node pre;
        public Node next;

        public Node(int key, int value){
            this.key = key;
            this.value = value;
        }
        public Node(){}
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

难度还是很大的


会议室

252. 会议室
给定一个会议时间安排的数组,每个会议时间都会包括开始和结束的时间
[[s1, e1], [s2, e2],…](si < ei)
请你判断一个人,能否参加这里的全部会议?

输入:[[0, 30], [5, 10], [15, 20]]
输出:false

输入:[[7, 10], [2, 4]]
输出:true


思路

感觉就是一个排序
按照会议开始时间排序
排序完毕后,检查后面会议的开始时间是否大于前一个会议的结束时间,如果大于或等于,则继续比较下一对。如果有一次为小于,说明不满足条件,直接返回false

public class 会议室{
	public boolean canAttendMeetings(int[][] intervals){
		if(intervals == null || intervals.length == 0) return true;

		//按照会议的开始时间,从小到大排序
		Arrays.sort(intervals, (int[] m1, int[] m2) -> {
			return m1[0] - m2[0];
		});

		for(int i = 1; i < intervals.length ; i++){
			if(intervals[i][0] < intervals[i - 1][1]){
				return false;
			}
		}

		return true;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值