
解题思路:
- 继承 LinkedHashMap: 内置双向链表,自动维护节点的插入顺序和访问顺序。
- LRU 淘汰逻辑: 覆盖 removeEldestEntry,当元素数量超过 capacity 时,移除最旧条目。removeEldestEntry 方法提供钩子(Hook)机制,在扩容时自动检查是否需要淘汰最旧节点自动触发,通过 LinkedHashMap 的内部机制,无需手动管理链表。
Java代码:
class LRUCache extends LinkedHashMap<Integer, Integer>{
private int capacity;
public LRUCache(int capacity) {
super(capacity, 0.75F, true);
this.capacity = capacity;
}
public int get(int key) {
return super.getOrDefault(key, -1);
}
public void put(int key, int value) {
super.put(key, value);
}
@Override
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
return size() > capacity;
}
}
哈希表+双向链表实现:
public class LRUCache {
class DLinkedNode {
int key;
int value;
DLinkedNode prev;
DLinkedNode next;
public DLinkedNode() {}
public DLinkedNode(int _key, int _value) {key = _key; value = _value;}
}
private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();
private int size;
private int capacity;
private DLinkedNode head, tail;
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
head = new DLinkedNode();
tail = new DLinkedNode();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
DLinkedNode node = cache.get(key);
if (node == null) {
return -1;
}
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
DLinkedNode node = cache.get(key);
if (node == null) {
DLinkedNode newNode = new DLinkedNode(key, value);
cache.put(key, newNode);
addToHead(newNode);
++size;
if (size > capacity) {
DLinkedNode tail = removeTail();
cache.remove(tail.key);
--size;
}
}
else {
node.value = value;
moveToHead(node);
}
}
private void addToHead(DLinkedNode node) {
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void removeNode(DLinkedNode node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void moveToHead(DLinkedNode node) {
removeNode(node);
addToHead(node);
}
private DLinkedNode removeTail() {
DLinkedNode res = tail.prev;
removeNode(res);
return res;
}
}
复杂度分析:

解题思路(迭代):
- 终止条件: 当前节点为空时返回。
- 递归逻辑: 先遍历左子树,再访问当前节点,最后遍历右子树。
Java代码:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
inorderHelper(root, result);
return result;
}
private void inorderHelper(TreeNode node, List<Integer> list) {
if (node == null) return;
inorderHelper(node.left, list);
list.add(node.val);
inorderHelper(node.right, list);
}
}
复杂度分析:
- 时间复杂度: 所有节点访问一次,时间复杂度均为 O(n)。
- 空间复杂度: 栈深度由树的高度决定,平衡树为 O(logn),链表为 O(n)。
解题思路(递归):
- 显式栈: 模拟递归调用栈,通过循环将左子树节点压栈,弹出后处理右子树。
Java代码:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
result.add(curr.val);
curr = curr.right;
}
return result;
}
}
复杂度分析:
- 时间复杂度: 所有节点访问一次,时间复杂度均为 O(n)。
- 空间复杂度: 栈最多存储 n 个节点(退化链表时),故空间复杂度为 O(n)。