题解 | #设计LRU缓存结构#

设计LRU缓存结构

http://www.nowcoder.com/practice/e3769a5f49894d49b871c09cadd13a61

普通解法

export function LRU(operators: number[][], k: number): number[] {
  const result: number[] = [];
  let cache: number[][] = [];
  operators.forEach((cmd) => {
    const [op, key] = cmd;
    let value: number;
    const index = cache.findIndex((c) => c && c[0] === key);
    let args = index === -1 ? undefined : cache[index];
    switch (op) {
      case 1:
        value = cmd[2];
        if (args) {
          args[1] = value;
        } else {
          args = [key, value];
        }
        if (cache.length >= k) {
          cache.splice(index === -1 ? 0 : index, 1);
        }
        cache.push(args);
        break;
      case 2:
        if (args) {
          value = args[1];
          cache.splice(index, 1);
          cache.push([key, value]);
        }
        result.push(args ? args[1] : -1);
        break;
    }
  });
  return result;
}

使用双向链表

export function LRU(operators: number[][], k: number): number[] {
  return useCache(operators, k);
}

export function useCache(operators: number[][], k: number): number[] {
  const result: number[] = [];
  let cache = new LRUCache(k);
  operators.forEach((cmd) => {
    const [op, key, value] = cmd;
    switch (op) {
      case 1:
        cache.add(new Node(key, value))
        break;
      case 2:
        const node = cache.get(key)
        result.push(node === -1 ? -1 : node.value);
        break;
    }
  });
  return result;
}

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 * lru design
 * @param operators int整型二维数组 the ops
 * @param k int整型 the k
 * @return int整型一维数组
 */
export function LRU(operators: number[][], k: number): number[] {
  return useCache(operators, k);
}

/**
 * 双向链表
 */
export function useCache(operators: number[][], k: number): number[] {
  const result: number[] = [];
  let cache = new LRUCache(k);
  operators.forEach((cmd) => {
    const [op, key, value] = cmd;
    switch (op) {
      case 1:
        cache.add(new Node(key, value))
        break;
      case 2:
        const node = cache.get(key)
        result.push(node === -1 ? -1 : node.value);
        break;
    }
  });
  return result;
}

class Node {
  public prev!: Node | undefined;
  public next!: Node | undefined;
  constructor(public key: number, public value: number) { }
}

class DoubleList {
  protected _size = 0;
  protected _first!: Node | undefined;
  protected _last!: Node | undefined;
  constructor(protected _limit: number) { }

  remove(node: Node | undefined): Node | undefined {
    if (!node) return node
    const prev = node.prev;
    const next = node.next;
    node.prev = undefined;
    node.next = undefined;
    if (prev) prev.next = next;
    if (next) next.prev = prev;
    if (node === this._first) this._first = next;
    if (node === this._last) this._last = prev;
    this._size--;
    return node;
  }

  put(node: Node): (callBack: (removedNode: Node | undefined) => void) => void {
    let removedNode: Node | undefined;
    if (this._size === this._limit) {
      removedNode = this._first;
      this.remove(this._first);
    }
    this._size++;

    if (!this._first) this._first = node;
    if (this._last) this._last.next = node;
    node.prev = this._last;
    this._last = node;
    return (callBack) => { callBack(removedNode) };
  }

  list(): Node[] {
    const result: Node[] = [];
    let tmp = this._last;
    while (tmp?.prev) {
      result.unshift(tmp);
      tmp = tmp.prev;
    }
    return result;
  }
}

class LRUCache {
  protected _list: DoubleList;
  protected _map: { [key: number]: Node } = {};
  constructor(limit: number) {
    this._list = new DoubleList(limit);
  }

  add(node: Node): this {
    const oldNode = this._map[node.key];
    if (oldNode) {
      this._list.remove(oldNode);
      delete this._map[oldNode.key]
    }
    this._list.put(node)(removedNode => removedNode && (delete this._map[removedNode.key]));
    this._map[node.key] = node;
    return this;
  }

  get(key: number) {
    const node = this._map[key];
    if (!node) return -1;
    this._list.remove(node);
    this._list.put(node);
    return node;
  }

  list(): Node[] {
    return this._list.list();
  }
}
全部评论

相关推荐

我见java多妩媚:大外包
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-24 20:55
阿里国际 Java工程师 2.7k*16.0
程序员猪皮:没有超过3k的,不太好选。春招再看看
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务