[LeetCode]460. LFU Cache

https://leetcode.com/problems/lfu-cache/#/description

实现一个 Least Frequently Used (LFU),保存访问频率最高的capacity个数,如果要淘汰的可能有多个数频率相同,则淘汰最后一次访问时间最靠前的

lintcode本题测试集不完整



用bucket链表,每个bucket内保存同一个count的所有元素,bucket内部用类似LRU来实现保存元素(head && tail),这样保证在O(1)时间内插入、删除特定元素或者进行淘汰

public class LFUCache {
    int capacity;
    DListBucket head;
    DListBucket tail;
    HashMap<Integer, Node> map;
    HashMap<Integer, DListBucket> bucketMap;
    
    class DListBucket {
        int count;
        Node nodeHead;
        Node nodeTail;
        DListBucket pre;
        DListBucket next;
        public DListBucket(int count) {
            this.count = count;
            nodeHead = new Node(0, 0, 0);
            nodeTail = new Node(0, 0, 0);
            nodeHead.next = nodeTail;
            nodeTail.pre = nodeHead;
        }
    }
    
    class Node {
        int key;
        int val;
        int count;
        Node pre;
        Node next;
        public Node(int key, int val, int count) {
            this.key = key;
            this.val = val;
            this.count = count;
        }
    }

    // @param capacity, an integer
    public LFUCache(int capacity) {
        // Write your code here
        this.capacity = capacity;
        head = new DListBucket(Integer.MIN_VALUE);
        tail = new DListBucket(Integer.MIN_VALUE);
        head.next = tail;
        tail.pre = head;
        map = new HashMap();
        bucketMap = new HashMap();
    }

    // @param key, an integer
    // @param value, an integer
    // @return nothing
    public void put(int key, int value) {
        // Write your code here
        if (capacity == 0) {
            return;
        }
        if (map.containsKey(key)) {
            Node node = map.get(key);
            node.pre.next = node.next;
            node.next.pre = node.pre;
            DListBucket next = null;
            if (bucketMap.get(node.count).next.count != node.count + 1) {
                next = insertBucket(node.count + 1, bucketMap.get(node.count));
            } else {
                next = bucketMap.get(node.count).next;
            }
            node.count++;
            node.val = value;
            node.pre = next.nodeTail.pre;
            node.next = next.nodeTail;
            next.nodeTail.pre = node;
            node.pre.next = node;
        } else {
            Node node = new Node(key, value, 1);
            map.put(key, node);
            DListBucket next = null;
            if (head.next.count != 1) {
                next = insertBucket(1, head);
            } else {
                next = head.next;
            }
            node.pre = next.nodeTail.pre;
            node.next = next.nodeTail;
            next.nodeTail.pre = node;
            node.pre.next = node;
            if (map.size() > capacity) {
                removeLastNode(node);
            }
        }
    }
    
    private void removeLastNode(Node cur) {
        Node nodeHead = head.next.nodeHead;
        Node node = null;
        if (nodeHead.next == cur && head.next.next.nodeHead.next != head.next.next.nodeTail) {
            node = head.next.next.nodeHead.next;
        } else {
            node = head.next.nodeHead.next;
        }
        node.pre.next = node.next;
        node.next.pre = node.pre;
        map.remove(node.key);
    }

    public int get(int key) {
        // Write your code here
        if (!map.containsKey(key)) {
            return -1;
        }
        Node node = map.get(key);
        node.pre.next = node.next;
        node.next.pre = node.pre;
        DListBucket next = null;
        if (bucketMap.get(node.count).next.count != node.count + 1) {
            next = insertBucket(node.count + 1, bucketMap.get(node.count));
        } else {
            next = bucketMap.get(node.count).next;
        }
        node.count++;
        node.pre = next.nodeTail.pre;
        node.next = next.nodeTail;
        next.nodeTail.pre = node;
        node.pre.next = node;
        return node.val;
    }
    
    private DListBucket insertBucket(int count, DListBucket pre) {
        DListBucket bucket = new DListBucket(count);
        bucket.next = pre.next;
        bucket.pre = pre;
        pre.next = bucket;
        bucket.next.pre = bucket;
        bucketMap.put(count, bucket);
        return bucket;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值