返回
设计模式大师课:揭秘 LeetCode 中的缓存与栈
后端
2023-10-06 19:54:02
在软件开发领域,设计模式是一套经过验证的解决方案,用于解决常见的设计问题。它们提供了可重用且可靠的蓝图,使开发人员能够创建灵活、可维护和可扩展的应用程序。在本文中,我们将深入探讨两种流行的设计模式:缓存和栈,并通过 LeetCode 中的实际问题来演示其应用。
1. 缓存(LRU)
问题: LeetCode 146. LRU 缓存
**** 设计一个缓存系统,其中最近使用的数据总是保留,而最久未使用的则会被删除。
解决方案:
缓存: 缓存是一种临时存储,用于在短期内快速访问数据。它通过将最近使用的数据保留在内存中,从而减少对慢速存储器(例如数据库)的访问。
LRU(最近最少使用)算法: LRU 算法是一种淘汰策略,它跟踪数据访问的顺序,并将最久未使用的项逐出缓存。
Java 实现:
public class LRUCache {
private Map<Integer, Node> cache;
private int capacity;
private Node head, tail;
public LRUCache(int capacity) {
this.cache = new HashMap<>();
this.capacity = capacity;
this.head = new Node();
this.tail = new Node();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
Node node = cache.get(key);
if (node == null) {
return -1;
}
remove(node);
insertAtHead(node);
return node.value;
}
public void put(int key, int value) {
Node node = cache.get(key);
if (node == null) {
node = new Node(key, value);
cache.put(key, node);
insertAtHead(node);
} else {
node.value = value;
remove(node);
insertAtHead(node);
}
if (cache.size() > capacity) {
removeTail();
}
}
private void remove(Node node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void insertAtHead(Node node) {
node.next = head.next;
head.next.prev = node;
head.next = node;
node.prev = head;
}
private void removeTail() {
Node node = tail.prev;
remove(node);
cache.remove(node.key);
}
private class Node {
int key;
int value;
Node prev;
Node next;
public Node() {}
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
}
2. 栈
问题: LeetCode 155. 最小栈
: 设计一个栈,除了正常的栈操作之外,还支持在任何时刻获取栈中的最小值。
解决方案:
栈: 栈是一种线性数据结构,遵循后进先出的原则。
辅助栈: 为了在恒定的时间复杂度内获取最小值,我们可以使用一个辅助栈来跟踪每个插入栈中的最小值。辅助栈始终保存到当前为止遇到的最小值。
Java 实现:
public class MinStack {
private Stack<Integer> stack;
private Stack<Integer> minStack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int x) {
stack.push(x);
if (minStack.isEmpty() || x <= minStack.peek()) {
minStack.push(x);
}
}
public int pop() {
int x = stack.pop();
if (x == minStack.peek()) {
minStack.pop();
}
return x;
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
结论
缓存和栈是广泛使用且功能强大的设计模式,对于优化应用程序性能至关重要。通过了解和应用这些模式,开发人员可以创建高效、可靠和可扩展的解决方案。LeetCode 中的示例问题为这些模式的实际应用提供了丰富的素材。深入理解这些模式将使您在软件开发职业生涯中获得巨大的优势。