5.15 二轮 链表

This commit is contained in:
zhangsan 2025-05-15 14:20:01 +08:00
parent 67697ee1a8
commit 4acf3b868b
5 changed files with 198 additions and 0 deletions

View File

@ -0,0 +1,88 @@
package linkedlist;
import java.util.HashMap;
import java.util.Map;
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<>();
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;
}
// 如果 key 存在先通过哈希表定位再移到头部
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
DLinkedNode node = cache.get(key);
if (node == null) {
// 如果 key 不存在创建一个新的节点
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 {
// 如果 key 存在先通过哈希表定位再修改 value并移到头部
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;
}
}

View File

@ -0,0 +1,40 @@
package linkedlist;
import java.util.*;
/**
* 题目 86. 分隔链表 (partition)
* 描述给你一个链表的头节点 head 和一个特定值 x 请你对链表进行分隔使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前
* 你应当 保留 两个分区中每个节点的初始相对位置
示例 1
输入head = [1,4,3,2,5,2], x = 3
输出[1,2,2,4,3,5]
* 链接https://leetcode.cn/problems/partition-list/
*/
public class Partition {
public ListNode partition(ListNode head, int x) {
// 虚拟头
ListNode smallDummy = new ListNode(0), largeDummy = new ListNode(0);
ListNode small = smallDummy, large = largeDummy;
// 一次遍历分拆到两条链
while (head != null) {
if (head.val < x) {
small.next = head;
small = small.next;
} else {
large.next = head;
large = large.next;
}
head = head.next;
}
// 断开>=x链尾避免环
large.next = null;
// 拼接两部分
small.next = largeDummy.next;
return smallDummy.next;
}
}

View File

@ -0,0 +1,13 @@
package linkedlist;
/**
* 题目 82. 删除排序链表中的重复元素 II (deleteDuplicates)
* 描述给定一个已排序的链表的头 head 删除原始链表中所有重复数字的节点只留下不同的数字 返回 已排序的链表
示例 2
输入head = [1,2,3,3,4,4,5]
输出[1,2,5]
* 链接https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/
*/
public class ReverseKGroup {
}

View File

@ -0,0 +1,44 @@
package linkedlist;
/**
* 题目 61. 旋转链表 (rotateRight)
* 描述给你一个链表的头节点 head 旋转链表将链表每个节点向右移动 k 个位置
示例 1
输入head = [1,2,3,4,5], k = 2
输出[4,5,1,2,3]
* 链接https://leetcode.cn/problems/rotate-list/
*/
public class RotateRight {
public ListNode rotateRight(ListNode head, int k) {
if (head == null || head.next == null || k == 0) {
return head;
}
// 1. 先遍历一遍求长度并连接成环
ListNode tail = head;
int n = 1;
while (tail.next != null) {
tail = tail.next;
n++;
}
// 如果 k n 取余后是 0旋转后还是原链表
int r = k % n;
if (r == 0) {
return head;
}
tail.next = head; // 形成环
// 2. 找到新尾 (n - r - 1)
int stepsToNewTail = n - r;
ListNode newTail = head;
for (int i = 1; i < stepsToNewTail; i++) {
newTail = newTail.next;
}
// 3. 新头是新尾的下一个节点
ListNode newHead = newTail.next;
// 4. 断开环
newTail.next = null;
return newHead;
}
}

View File

@ -0,0 +1,13 @@
package linkedlist;
import org.junit.Test;
import static org.junit.Assert.*;
public class PartitionTest {
@Test
public void partition() {
}
}