题目描述:
给定一个带有头结点 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。示例 1
输入:[1,2,3,4,5]
输出:此列表中的结点 3 示例 2:
示例 2
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4
提交结果:
解法一 : 两次遍历
核心思想:
- 遍历第一编,统计出链表的结点个数
- 计算中间结点的位置
- 遍历第二遍,找中间结点
注:假设链表的结点个数为count
不论它是奇数还是偶数,中间结点的位置都可以通过count / 2 + 1
计算得出,(第一个结点的位置为1)
代码实现:
public class MiddleNode {
public ListNode middleNode(ListNode head){
// 空链表或者一个结点的链表
if(head == null || head.next == null){
return head;
}
ListNode cur = head;
int count = 0;
// 计算结点个数
while(cur != null){
count++;
cur = cur.next;
}
//重新指向头结点,准备第二次遍历
cur = head;
// 找中间结点
for(int i = 1; i < count / 2 + 1; i++){
cur = cur.next;
}
return cur;
}
}
解法二: 快慢指针法(只需遍历一次)
核心思想:
- 设立两个指针
fast,slow
- 快指针
fast
一次走两步,慢指针slow
一次走一步。 - 当快指针走到尾的时候,慢指针刚好来到中间位置,且可以同时处理奇偶结点的情况。
代码实现
public class MiddleNode {
public ListNode middleNode(ListNode head){
// 空链表或者一个结点的链表
if(head == null || head.next == null){
return head;
}
// 快指针
ListNode fast = head;
//慢指针
ListNode slow = head;
while(fast != null && fast.next != null){
// 一次走两步
fast = fast.next.next;
// 走一步
slow = slow.next;
}
return slow;
}