diff --git a/src/main/java/linkedlist/LRUCache.java b/src/main/java/linkedlist/LRUCache.java new file mode 100644 index 0000000..e677f9b --- /dev/null +++ b/src/main/java/linkedlist/LRUCache.java @@ -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 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; + } +} diff --git a/src/main/java/linkedlist/Partition.java b/src/main/java/linkedlist/Partition.java new file mode 100644 index 0000000..f3551df --- /dev/null +++ b/src/main/java/linkedlist/Partition.java @@ -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; + } +} diff --git a/src/main/java/linkedlist/ReverseKGroup.java b/src/main/java/linkedlist/ReverseKGroup.java new file mode 100644 index 0000000..c34adbe --- /dev/null +++ b/src/main/java/linkedlist/ReverseKGroup.java @@ -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 { +} diff --git a/src/main/java/linkedlist/RotateRight.java b/src/main/java/linkedlist/RotateRight.java new file mode 100644 index 0000000..cf39cb6 --- /dev/null +++ b/src/main/java/linkedlist/RotateRight.java @@ -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; + } +} diff --git a/src/test/java/linkedlist/PartitionTest.java b/src/test/java/linkedlist/PartitionTest.java new file mode 100644 index 0000000..c71497b --- /dev/null +++ b/src/test/java/linkedlist/PartitionTest.java @@ -0,0 +1,13 @@ +package linkedlist; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class PartitionTest { + + @Test + public void partition() { + + } +} \ No newline at end of file