23. 合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) {
return null;
}
//优先队列
PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val - o2.val;
}
});
ListNode dumyHead = new ListNode(0);
ListNode p = dumyHead;
//加入全部的链表头节点
for (ListNode node : lists) {
if (node != null) {
pq.offer(node);
}
}
//取出头节点最小的链表,然后将头节点接到p,将头节点之后的链表再放回到优先队列之中
while (!pq.isEmpty()) {
p.next = pq.poll();
p = p.next;
if (p.next != null) {
pq.offer(p.next);
}
}
return dumyHead.next;
}
}
146. LRU 缓存机制
LRU 缓存机制
实现 LRUCache 类:
- LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
- int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
- void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
class LRUCache {
/*
实现原理:哈希表+双向链表
哈希表储存 <key , Double Linked List>
双向链表: key, val, pre, next
LRUCache:一个map,当前大小:size,容量 cap,双向链表:DLinkedNode的tail, head
基本api:基于双向链表进行操作,
get set:基于map和基本api操作
*/
//双向链表
class DLinkedNode {
int key;
int val;
DLinkedNode pre;
DLinkedNode next;
public DLinkedNode() {
}
public DLinkedNode(int key, int val) {
this.key = key;
this.val = val;
}
}
private Map<Integer, DLinkedNode> map = new HashMap<>();
private int size;
private int capacity;
private DLinkedNode head;
private DLinkedNode tail;
public LRUCache(int capacity) {
this.size = 0;
this.capacity = capacity;
// 使用伪头部和伪尾部节点
head = new DLinkedNode();
tail = new DLinkedNode();
head.next = tail;
tail.pre = head;
}
public int get(int key) {
DLinkedNode node = map.get(key);
if (node == null) {
return -1;
}
// 如果 key 存在,先通过哈希表定位,再移到头部
moveToHead(node);
return node.val;
}
public void put(int key, int value) {
DLinkedNode node = map.get(key);
if (node == null) {
//key不存在,则创建一个新的节点
DLinkedNode newNode = new DLinkedNode(key, value);
//添加进哈希表
map.put(key, newNode);
//添加到双向链表的头部
addToHead(newNode);
size++;
if (size > capacity) {
//超出了容量,删除双线链表的尾部节点
DLinkedNode tail = removeTail();
//删除哈希表中对应的项
map.remove(tail.key);
size--;
}
} else {
//若key存在,则先通过哈希表定位,再修改value,并移动到头部
node.val = value;
moveToHead(node);
}
}
private void addToHead(DLinkedNode node) {
node.pre = head;
node.next = head.next;
node.next.pre = node;
head.next = node;
}
//移除节点
private void remove(DLinkedNode node) {
node.pre.next = node.next;
node.next.pre = node.pre;
}
//移动节点到首位置
private void moveToHead(DLinkedNode node) {
remove(node);
addToHead(node);
}
//删除最后一个节点
private DLinkedNode removeTail() {
DLinkedNode node = tail.pre;
remove(node);
return node;
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/