欢迎来找茬-LRU-Leetcode

202 阅读2分钟

这道题最近热度比较高,就试着用两种写法就整了整,第一种是模仿大佬写的,用map去写的,第二种是用对象键值对+链表写的。 原题连接:leetcode-cn.com/problems/lr…

原题最关键的地方在于函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。这也是为什么我们会采用键值对+双向链表 或者map。map不多说了。键值对+双向链表才是此题的精髓。先让我们看看双向链表的的基本属性。

class NodeLink {
    public next // 下一个链表
    public pre  // 上一个链表
    public val  // 值
    public key  // 键
    constructor(val, key?, next?, pre?) {
        this.val = val
        this.key = key
        this.next = next
        this.pre = pre
    }
}

LinkMap类是此题的关键,几个关键的属性headLink,为了能够快速的添加移动元素到头部。 footLink为了能够快速的删除尾部数据。

class LRUCache {
    private capacity:number
    private caches:Map<any,any> =new Map()
    constructor(capacity: number) {
         this.capacity = capacity
    }

    get(key: number): number {
        const cache:any = this.caches.get(key)
        if(typeof cache === 'undefined'){
            return -1
        }
        this.caches.delete(key)
        this.caches.set(key,cache)
        return cache
    }

    put(key: number, value: number): void {
       if( this.caches.has(key)){
            this.caches.delete(key)
       }
        this.caches.set(key,value)
        const keys:any = this.caches.keys()
        // @ts-ignore
        while(this.caches.size > this.capacity){
            this.caches.delete(keys.next().value)
        }
    }
}
```
```
第二种写法 
```
class NodeLink {
    public next
    public pre
    public val
    public key
    constructor(val, key?, next?, pre?) {
        this.val = val
        this.key = key
        this.next = next
        this.pre = pre
    }
}

class LinkMap {
    // map 
    public map: any = {}
    // 顶部的链表
    private headLink: NodeLink = new NodeLink(-1)
    private footLink: NodeLink = new NodeLink(-1)
    private len: number = 0
    constructor() {
        // 初始 头尾向连
        this.headLink.next = this.footLink
        this.footLink.pre = this.headLink
    }
    // 保存的数据长度
    size() {
        return this.len
    }
    // 保存
    set(key: any, value: any) {
        let node: NodeLink
        if (this.has(key)) {
            node = this.map[key]
            node.val = value
            this.moveToHead(node)
            // 如果下一个没有说明最后一个
        } else {
            node = new NodeLink(value, key)
            this.addToHead(node)
            this.len++
        }
        this.map[key] = node
    }
    // 前后交换
    swipe(node) {
        node.pre.next = node.next
        node.next.pre = node.pre
    }
    // 添加到头部
    addToHead(node) {
        node.pre = this.headLink
        node.next = this.headLink.next
        this.headLink.next.pre = node
        this.headLink.next = node
    }
    // 交换到头部
    moveToHead(node) {
        this.swipe(node)
        this.addToHead(node)
    }
    // 判断是否存在 此 node
    has(key: any) {
        return this.map[key] != undefined
    }
    // 获取数据
    get(key: any) {
        return this.map[key]
    }
    // 删除尾部
    deleteLast() {
        this.map[this.footLink.pre.key] = undefined
        this.swipe(this.footLink.pre)
        this.len--
    }
}

class LRUCache {
    private capacity = 0
    private linkMap: LinkMap
    constructor(capacity: number) {
        this.capacity = capacity
        this.linkMap = new LinkMap()
    }

    get(key: number): number {
        if (!this.linkMap.has(key)) {
            return -1
        }
        const node = this.linkMap.get(key)
        this.linkMap.moveToHead(node)
        return node.val
    }

    put(key: number, value: number): void {
        this.linkMap.set(key, value)
        while (this.linkMap.size() > this.capacity) {
            this.linkMap.deleteLast()
        }
    }
}
```