目录
题目链接:LeetCode876.链表的L中间结点
一.题目要求
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
提示:
给定链表的结点数介于 1 和 100 之间。
二.解题思路
在此处介绍两种解题方法:
1.求总长度后求中间长度
首先,题目要求找到中间结点,那我们首先就会联想到可以求出来总长度,然后通过循环遍历的方式找到1/2总长度的结点,即为中间结点,这里为了便于观看,可以将其写成函数。
求链表总长度函数:
private int sizeOf(ListNode head){
//时间复杂度:O(n)
//空间复杂度:O(1)
int size=0;
ListNode cur=head;
while(cur!=null){
size++;
cur=cur.next;
}
return size;
}
通过限制长度从而循环遍历寻找中间结点:
//时间复杂度:O(n)
//空间复杂度:O(1)
public ListNode middleNode(ListNode head) {
int size=sizeOf(head);
int x=size/2;
ListNode ans=head;
for(int i=0;i<x;i++){
ans=ans.next;
}
return ans;
}
2.使用快慢指针求解
其实这里的一快一慢其实是一前一后,快指针在前,慢指针在后。我们设定一个快指针,一个慢指针,当慢指针走一步时,快指针走两步,这样当快指针走到链表尾部时,慢指针正好走到中间结点的位置,这时只需要返回慢指针结点即可。
使用快慢指针解决问题的重点在于什么时候进行快指针到达链表尾部的判断,本题目要求如果有两个中间结点(链表结点数是偶数),则返回第二个结点,所以我们需要自己分情况讨论究竟采取哪种执行顺序可以得到想要的结果。
情况分类:
以 "慢->快->判断->快->判断" 举例:
奇数的情况:
偶数的情况:
三.具体代码
1.求总长度后求中间长度
class Solution {
private int sizeOf(ListNode head){
//时间复杂度:O(n)
//空间复杂度:O(1)
int size=0;
ListNode cur=head;
while(cur!=null){
size++;
cur=cur.next;
}
return size;
}
//时间复杂度:O(n)
//空间复杂度:O(1)
public ListNode middleNode(ListNode head) {
int size=sizeOf(head);
int x=size/2;
ListNode ans=head;
for(int i=0;i<x;i++){
ans=ans.next;
}
return ans;
}
2.使用快慢指针求解
class Solution {
//时间复杂度:O(n)
//空间复杂度:O(1)
public ListNode middleNode(ListNode head) {
if(head==null){
return null;
}
ListNode fast=head;
ListNode slow=head;
while(true){
fast=fast.next;
if(fast==null){
break;
}
slow=slow.next;
fast=fast.next;
if(fast==null){
break;
}
}
return slow;
}
}
四.运行截图
如想了解链表(LinkedList)相关知识,请查阅:
如有建议或想法,欢迎一起讨论学习~