最优解:快慢指针
public ListNode middleNode(ListNode head){
if(head==null){//链表为空
return null;
}
if(head.next==null){//只有一个节点
return head;
}
ListNode fast=head;
ListNode slow=head;//快慢指针在同一节点
while (fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next;
}
return slow;
}
快慢指针(也称为龟兔赛跑算法)来找到链表的中间节点,是一种非常高效且简洁的算法思想。这种算法的核心在于利用两个指针以不同的速度遍历链表,从而在一次遍历中就能找到中间节点。
算法思想
- 初始化:
- 创建两个指针,
slow和fast,都指向链表的头节点head。
- 创建两个指针,
- 遍历链表:
- 在遍历链表的过程中,
slow指针每次向前移动一步(即slow = slow.next),而fast指针每次向前移动两步(即fast = fast.next.next)。 - 由于
fast指针的速度是slow指针的两倍,因此当fast指针到达链表末尾时(即fast或fast.next为null),slow指针将位于链表的中间位置(或对于偶数长度的链表,位于两个中间节点中的第二个)。
- 在遍历链表的过程中,
- 处理边界情况:
- 如果链表为空(
head == null),则直接返回null,因为没有中间节点。 - 如果链表只有一个节点(
head.next == null),则该节点就是中间节点,直接返回head。
- 如果链表为空(
- 返回结果:
- 当
fast指针到达链表末尾时,循环结束。此时,slow指针所指向的节点就是链表的中间节点(或偶数长度链表中的第二个中间节点)。
- 当
优点
- 时间复杂度:O(n),其中 n 是链表的长度。因为只需要遍历链表一次。
- 空间复杂度:O(1)。只使用了两个额外的指针,不随链表长度的增加而增加。
应用场景
- 找到链表的中间节点。
- 在一些需要分割链表的问题中,如“将链表从中间节点断开”。
- 在某些递归或迭代算法中,需要确定链表的中点以优化性能或简化逻辑。
示例
假设链表为 1 -> 2 -> 3 -> 4 -> 5,则:
slow和fast初始时都指向节点1。- 第一次循环后,
slow指向2,fast指向3。 - 第二次循环后,
slow指向3,fast指向5。 - 第三次循环时,
fast尝试指向5.next,但发现5.next为null,因此循环结束。 - 此时,
slow指向3,即链表的中间节点(对于奇数长度的链表)。
对于偶数长度的链表,如 1 -> 2 -> 3 -> 4,算法会返回第二个中间节点(即 3),但同样可以根据需要调整算法以返回第一个中间节点。

361

被折叠的 条评论
为什么被折叠?



