206.反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
方法一:迭代
思路:
- 设3个指针,prev、curr、next
- prev为null,curr等于head,反转时让curr.next等于prev
- 因为curr要反转,以免后面的链段了,所以要有一个next变量保存curr.next
复杂度分析var reverseList = function(head) {let prev = null;let curr = head;while (curr) {const next = curr.next;curr.next = prev;prev = curr;curr = next;}return prev;};
- 拆分成两个问题,head和除了head外的反转问题
- 再从除了head外的问题拆成两个小问题,递归下去
- 到剩一个最小问题,开始回归。
复杂度分析.var reverseList = function(head) {if (head == null || head.next == null) {return head;}const newHead = reverseList(head.next);head.next.next = head;head.next = null;return newHead;};
- 时间复杂度: O(m),其中n是链表的长度。需要对链表的每个节点进行反转操作。
空间复杂度: O(n),其中n是链表的长度。空间复杂度主要取决于递归调用的栈空间,最多为n层。
146.LRU缓存
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
- int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
- void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
class LRUCache {constructor(capacity) {this.capacity = capacitythis.map = new Map();}get(key) {let val = this.map.get(key);if (val === undefined) return -1;this.map.delete(key); // 因为被用过一次,原有位置删除this.map.set(key, val); // 放入最下面表示最新使用return val;}put(key, val) {if (this.map.has(key)) this.map.delete(key); // 如果有,删除this.map.set(key, val); // 放到最下面表示最新使用if (this.map.size > this.capacity) {// 这里有个知识点// map的entries方法,还有keys方法(可以看mdn)),会返回一个迭代器// 迭代器调用next也是顺序返回,所以返回第一个的值就是最老的,找到并删除即可this.map.delete(this.map.entries().next().value[0])}}};
class ListNode {constructor(key, value) {this.key = keythis.value = valuethis.next = nullthis.prev = null}}class LRUCache {constructor(capacity) {this.capacity = capacitythis.hash = {}this.count = 0this.dummyHead = new ListNode()this.dummyTail = new ListNode()this.dummyHead.next = this.dummyTailthis.dummyTail.prev = this.dummyHead}get(key) {let node = this.hash[key]if (node == null) return -1this.moveToHead(node)return node.value}put(key, value) {let node = this.hash[key]if (node == null) {if (this.count == this.capacity) {this.removeLRUItem()}let newNode = new ListNode(key, value)this.hash[key] = newNodethis.addToHead(newNode)this.count++} else {node.value = valuethis.moveToHead(node)}}moveToHead(node) {this.removeFromList(node)this.addToHead(node)}removeFromList(node) {let temp1 = node.prevlet temp2 = node.nexttemp1.next = temp2temp2.prev = temp1}addToHead(node) {node.prev = this.dummyHeadnode.next = this.dummyHead.nextthis.dummyHead.next.prev = nodethis.dummyHead.next = node}removeLRUItem() {let tail = this.popTail()delete this.hash[tail.key]this.count--}popTail() {let tail = this.dummyTail.prevthis.removeFromList(tail)return tail}}
