From 9e0b5945a264e5255b44085b878d052fb52ffa68 Mon Sep 17 00:00:00 2001 From: zhangsan <646228430@qq.com> Date: Wed, 25 Jun 2025 13:48:19 +0800 Subject: [PATCH] =?UTF-8?q?6.25=20=E4=BA=8C=E5=88=B7hot100=20=E9=93=BE?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/linkedlist/AddTwoNumbers.java | 1 + src/main/java/linkedlist/DetectCycle.java | 26 +++++----- src/main/java/linkedlist/HasCycle.java | 29 +++++++---- src/main/java/linkedlist/IsPalindrome.java | 7 +-- src/main/java/linkedlist/MergeTwoLists.java | 1 + .../java/linkedlist/RemoveNthFromEnd.java | 48 +++++++++++++++++-- 6 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/main/java/linkedlist/AddTwoNumbers.java b/src/main/java/linkedlist/AddTwoNumbers.java index 37304d4..3f30264 100644 --- a/src/main/java/linkedlist/AddTwoNumbers.java +++ b/src/main/java/linkedlist/AddTwoNumbers.java @@ -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); diff --git a/src/main/java/linkedlist/DetectCycle.java b/src/main/java/linkedlist/DetectCycle.java index d8cae22..9bda474 100644 --- a/src/main/java/linkedlist/DetectCycle.java +++ b/src/main/java/linkedlist/DetectCycle.java @@ -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,28 +28,24 @@ 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; + ptr = ptr.next; slow = slow.next; } return ptr; } } - return null; + return null; // fast 走到末尾, 无环 } } diff --git a/src/main/java/linkedlist/HasCycle.java b/src/main/java/linkedlist/HasCycle.java index 6c98c0d..85517c8 100644 --- a/src/main/java/linkedlist/HasCycle.java +++ b/src/main/java/linkedlist/HasCycle.java @@ -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; + 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; // 相遇则有环 } - slow = slow.next; - fast = fast.next.next; } - return true; + + return false; // 跳出循环说明没有环 } + } diff --git a/src/main/java/linkedlist/IsPalindrome.java b/src/main/java/linkedlist/IsPalindrome.java index 219e3a1..c0c90a2 100644 --- a/src/main/java/linkedlist/IsPalindrome.java +++ b/src/main/java/linkedlist/IsPalindrome.java @@ -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; Listlist=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 } diff --git a/src/main/java/linkedlist/MergeTwoLists.java b/src/main/java/linkedlist/MergeTwoLists.java index 3ebd6a0..ed6cb87 100644 --- a/src/main/java/linkedlist/MergeTwoLists.java +++ b/src/main/java/linkedlist/MergeTwoLists.java @@ -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); diff --git a/src/main/java/linkedlist/RemoveNthFromEnd.java b/src/main/java/linkedlist/RemoveNthFromEnd.java index e832445..f0de96f 100644 --- a/src/main/java/linkedlist/RemoveNthFromEnd.java +++ b/src/main/java/linkedlist/RemoveNthFromEnd.java @@ -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) { HashMapmap=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 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; + } + }