不使用map和set实现LRU——那用List?

遇到一道面试题,不使用map和set实现LRU,要求get的时间复杂度为O(logn),put的时间复杂度不超过O(n)。想到了用ArrayList来实现,保存有序的key。然而牵涉add节点,在保证有序的情况下通过插入排序在ArrayList中插入一个新节点,时间复杂度不能保证O(n),粗略写了一个代码,供大家提出一些建议。

class LRUCache {
    class ListNode {
        int key;
        int val;
        ListNode next;
        ListNode pre;
        public ListNode(int key, int val) {
            this.key = key;
            this.val = val;
            next = null;
            pre = null;
        }
    }

    private int capacity;
    private List<ListNode> list;
    private int getId;
    private ListNode tail;
    private ListNode head;

    public LRUCache(int k) {
        capacity = k;
        list = new ArrayList<>();
        head = new ListNode(-1, -1);
        tail = new ListNode(-1, -1);
        head.next = tail;
        tail.pre = head;
    }
 // 二分查找
    public int search(int key) {
        int left = 0, right = list.size() - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            ListNode node = list.get(mid);
            if (node.key > key) {
                right = mid - 1;
            } else if (node.key < key) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }
// get
    public int get(int key) {
        getId = search(key);
        if (getId == -1) {
            return getId;
        }
        ListNode node = list.get(getId);
        node.pre.next = node.next;
        node.next.pre = node.pre;
        addToTail(node);
        return node.val;
    }
// put
    public void put(int key, int val) {
        if (get(key) != -1) {
            list.get(getId).val = val;
            return;
        }
        ListNode node = new ListNode(key, val);
        addToTail(node);
        int i = 0;
        for (; i < list.size(); ++i) {
            if (list.get(i).key > key) {
                list.add(i, node); // 这里牵涉到get和add两个操作,不能保证put的时间复杂度为O(n)
                break;
            }
        }
        if (i == list.size()) list.add(node);
        if (list.size() > capacity) {
            getId = search(head.next.key);
            list.remove(getId);
            head.next = head.next.next;
            head.next.pre = head;
        }
    }

    public void addToTail(ListNode node) {
        node.pre = tail.pre;
        node.next = tail;
        node.pre.next = node;
        tail.pre = node;
    }
}

  

原文地址:https://www.cnblogs.com/peony-jing/p/13681135.html