6.25 二刷hot100 链表

This commit is contained in:
zhangsan 2025-06-25 13:48:19 +08:00
parent c1899dd270
commit 9e0b5945a2
6 changed files with 82 additions and 30 deletions

View File

@ -8,6 +8,7 @@ package linkedlist;
* 链接https://leetcode.cn/problems/add-two-numbers/
*/
// 二刷会做
public class AddTwoNumbers {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1);

View File

@ -7,10 +7,12 @@ import java.util.HashSet;
* 描述给定一个链表的头节点 head 返回链表开始入环的第一个节点 如果链表无环则返回 null
* 如果链表中有某个节点可以通过连续跟踪 next 指针再次到达则链表中存在环 为了表示给定链表中的环评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置索引从 0 开始如果 pos -1则在该链表中没有环注意pos 不作为参数进行传递仅仅是为了标识链表的实际情况
* 不允许修改 链表
进阶你是否可以使用 O(1) 空间解决此题
* 链接https://leetcode.cn/problems/linked-list-cycle-ii/
*/
//二刷不会做 推导忘记
public class DetectCycle {
//哈希
public ListNode detectCycle1(ListNode head) {
@ -26,20 +28,16 @@ public class DetectCycle {
}
return null;
}
//Floyd 快慢指针
//Floyd 快慢指针 如果链表中存在环 fast 指针最终将再次与 slow 指针在环中相遇
public ListNode detectCycle(ListNode head) {
if (head == null) {
return null;
}
if (head == null) return null;
ListNode slow = head, fast = head;
while (fast != null) {
slow = slow.next;
if (fast.next != null) {
fast = fast.next.next;
} else {
return null;
}
if (fast == slow) {
// fast fast.next null 时跳出说明无环
while (fast != null && fast.next != null) {
slow = slow.next; // 慢指针走一步
fast = fast.next.next; // 快指针走两步
if (slow == fast) { // 相遇确认有环
// 第二阶段找到环的入口
ListNode ptr = head;
while (ptr != slow) {
ptr = ptr.next;
@ -48,6 +46,6 @@ public class DetectCycle {
return ptr;
}
}
return null;
return null; // fast 走到末尾 无环
}
}

View File

@ -7,12 +7,14 @@ import java.util.HashSet;
* 描述给你一个链表的头节点 head 判断链表中是否有环
* 如果链表中有某个节点可以通过连续跟踪 next 指针再次到达则链表中存在环 为了表示给定链表中的环评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置索引从 0 开始注意pos 不作为参数进行传递 仅仅是为了标识链表的实际情况
* 如果链表中存在环 则返回 true 否则返回 false
进阶你能用 O(1)常量内存解决此问题吗
* 链接https://leetcode.cn/problems/linked-list-cycle/
输入head = [3,2,0,-4], pos = 1
输出true
解释链表中有一个环其尾部连接到第二个节点
*/
//二刷会做
public class HasCycle {
//哈希法
public boolean hasCycle1(ListNode head) {
@ -58,19 +60,26 @@ public class HasCycle {
// 走到空指针说明无环
return false;
}
//快慢指针法
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
if (head == null) return false;
// 快慢指针都从 head 出发
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
ListNode fast = head;
// fast fast.next null 说明已经到链表末尾无环
while (fast != null && fast.next != null) {
slow = slow.next; // 慢指针走一步
fast = fast.next.next; // 快指针走两步
// 每走一步就检查一次相遇
if (slow == fast) {
return true; // 相遇则有环
}
}
return false; // 跳出循环说明没有环
}
}

View File

@ -6,12 +6,13 @@ import java.util.List;
/**
* 题目234. 回文链表 (isPalindrome)
* 描述给你一个单链表的头节点 head 请你判断该链表是否为回文链表如果是返回 true 否则返回 false
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题
* 链接https://leetcode.cn/problems/palindrome-linked-list/
*/
//二刷会做
public class IsPalindrome {
public boolean isPalindrome(ListNode head) {
public boolean isPalindrome1(ListNode head) {
ListNode temp=head;
List<Integer>list=new ArrayList<>();
while (head!=null){
@ -26,7 +27,7 @@ public class IsPalindrome {
return true;
}
//快慢指针 + 链表反转
public boolean isPalindrome1(ListNode head) {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true; // 空链表或只有一个节点直接返回 true
}

View File

@ -10,6 +10,7 @@ import java.util.List;
* 链接https://leetcode.cn/problems/merge-two-sorted-lists/
*/
//二刷会做
public class MergeTwoLists {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode head = new ListNode(-1);

View File

@ -7,12 +7,16 @@ import java.util.LinkedList;
/**
* 题目 19. 删除链表的倒数第 N 个结点 (removeNthFromEnd)
* 描述给你一个链表删除链表的倒数第 n 个结点并且返回链表的头结点
进阶你能尝试使用一趟扫描实现吗
* 链接https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
*/
//二刷会做
public class RemoveNthFromEnd {
//思路
//1. 遍历一遍链表用哈希表存储每个节点的位置
//2. 找到倒数第n个节点的前一个节点修改指针
//3. 注意边界情况如删除头节点
public ListNode removeNthFromEnd1(ListNode head, int n) {
HashMap<Integer,ListNode>map=new HashMap<>();
int k=0;
@ -28,7 +32,11 @@ public class RemoveNthFromEnd {
return head;
}
//入栈 出栈
public ListNode removeNthFromEnd(ListNode head, int n) {
//思路
//1. 遍历一遍链表用栈存储每个节点
//2. 找到倒数第n个节点的前一个节点修改指针
//3. 注意边界情况如删除头节点
public ListNode removeNthFromEnd2(ListNode head, int n) {
ListNode dummy = new ListNode(0,head);
Deque<ListNode> stack = new LinkedList<>();
ListNode cur = dummy;
@ -44,4 +52,38 @@ public class RemoveNthFromEnd {
ListNode ans = dummy.next;
return ans;
}
//思路
//1. 定义两个指针first和second都指向 dummy
//2. first 向前走 n+1
//3. 同时移动两指针保持 n+1 步差距
//4. 此时 second.next 是要删除的节点直接跳过它
//5. 返回删除后的链表头
public ListNode removeNthFromEnd(ListNode head, int n) {
// 1. 创建虚拟头节点
ListNode dummy = new ListNode(0);
dummy.next = head;
// 2. 初始化快慢指针都指向 dummy
ListNode first = dummy;
ListNode second = dummy;
// 3. 先让 first 向前走 n+1
for (int i = 0; i < n + 1; i++) {
first = first.next;
}
// 4. 同时移动两指针保持 n+1 步差距
while (first != null) {
first = first.next;
second = second.next;
}
// 5. 此时 second.next 是要删除的节点直接跳过它
second.next = second.next.next;
// 6. 返回删除后的链表头
return dummy.next;
}
}