快慢指针【中分链表、判断链表中是否存在环】

[复制链接]
发表于 2025-10-20 02:32:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一、中分链表:找到链表的中心节点

Java 实现
  1. class ListNode {
  2.     int val;
  3.     ListNode next;
  4.     ListNode(int val) {
  5.         this.val = val;
  6.         this.next = null;
  7.     }
  8. }
  9. public class MiddleOfLinkedList {
  10.     public ListNode findMiddleNode(ListNode head) {
  11.         if (head == null) {
  12.             return null;
  13.         }
  14.         
  15.         ListNode slow = head;
  16.         ListNode fast = head;
  17.         
  18.         // 快指针每次走两步,慢指针每次走一步
  19.         while (fast != null && fast.next != null) {
  20.             slow = slow.next;
  21.             fast = fast.next.next;
  22.         }
  23.         
  24.         // 慢指针指向中间节点
  25.         return slow;
  26.     }
  27.     public static void main(String[] args) {
  28.         // 示例链表:1 -> 2 -> 3 -> 4 -> 5
  29.         ListNode head = new ListNode(1);
  30.         head.next = new ListNode(2);
  31.         head.next.next = new ListNode(3);
  32.         head.next.next.next = new ListNode(4);
  33.         head.next.next.next.next = new ListNode(5);
  34.         MiddleOfLinkedList solution = new MiddleOfLinkedList();
  35.         ListNode middle = solution.findMiddleNode(head);
  36.         System.out.println("中间节点值: " + middle.val); // 输出: 3
  37.     }
  38. }
复制代码
示例

输入链表:1 -> 2 -> 3 -> 4 -> 5
输出:3
输入链表:1 -> 2 -> 3 -> 4 -> 5 -> 6
输出:4

二、判断链表中是否存在环

Java 实现
  1. class ListNode {
  2.     int val;
  3.     ListNode next;
  4.     ListNode(int val) {
  5.         this.val = val;
  6.         this.next = null;
  7.     }
  8. }
  9. public class LinkedListCycle {
  10.     public ListNode detectCycle(ListNode head) {
  11.         if (head == null || head.next == null) {
  12.             return null;
  13.         }
  14.         
  15.         ListNode slow = head;
  16.         ListNode fast = head;
  17.         
  18.         // 判断是否有环
  19.         while (fast != null && fast.next != null) {
  20.             slow = slow.next;
  21.             fast = fast.next.next;
  22.             
  23.             // 快慢指针相遇,说明有环
  24.             if (slow == fast) {
  25.                 break;
  26.             }
  27.         }
  28.         
  29.         // 无环
  30.         if (fast == null || fast.next == null) {
  31.             return null;
  32.         }
  33.         
  34.         // 找到环的入口
  35.         fast = head;
  36.         while (fast != slow) {
  37.             fast = fast.next;
  38.             slow = slow.next;
  39.         }
  40.         
  41.         return slow;
  42.     }
  43.     public static void main(String[] args) {
  44.         // 示例链表:1 -> 2 -> 3 -> 4 -> 5 -> 2(节点5指向节点2,形成环)
  45.         ListNode head = new ListNode(1);
  46.         head.next = new ListNode(2);
  47.         head.next.next = new ListNode(3);
  48.         head.next.next.next = new ListNode(4);
  49.         head.next.next.next.next = new ListNode(5);
  50.         head.next.next.next.next.next = head.next; // 形成环
  51.         LinkedListCycle solution = new LinkedListCycle();
  52.         ListNode cycleNode = solution.detectCycle(head);
  53.         if (cycleNode != null) {
  54.             System.out.println("环的入口节点值: " + cycleNode.val); // 输出: 2
  55.         } else {
  56.             System.out.println("链表中无环");
  57.         }
  58.     }
  59. }
复制代码
示例

输入链表:1 -> 2 -> 3 -> 4 -> 5 -> 2(节点5指向节点2,形成环)
输出:2
输入链表:1 -> 2 -> 3 -> 4 -> 5
输出:链表中无环

三、核心头脑总结


  • 快慢指针的速率差:

    • 快指针每次移动两步,慢指针每次移动一步;
    • 在中分链表中,快指针到达末端时,慢指针恰恰在中心;
    • 在判断环时,快指针会追上慢指针。

  • 时间复杂度:

    • 中分链表:O(n),此中 n 是链表长度;
    • 判断环:O(n),最多遍历链表两次。

  • 空间复杂度:O(1),只使用了常数级别的额外空间。

四、练习题


  • 中分链表:

    • 输入:1 -> 2 -> 3 -> 4 -> 5 -> 6
    • 输出:4

  • 判断环:

    • 输入:1 -> 2 -> 3 -> 4 -> 5 -> 3(节点5指向节点3,形成环)
    • 输出:3


通过 Java 实现 快慢指针本领,可以高效办理链表中的常见标题。把握这一本领,链表标题将不再是困难!
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表