算法系列-力扣876-求链表的中间节点

求链表中间节点,如果有两个中间节点取后面那个

链表定义

```

// @lc code=start

/**

* Definition for singly-linked list.

* public class ListNode {

* int val;

* ListNode next;

* ListNode() {}

* ListNode(int val) { this.val = val; }

* ListNode(int val, ListNode next) { this.val = val; this.next = next; }

* }

*/

```

方法一:计数取一半

解题方法:

先计算链表一共有多少个节点n

n/2,得到中间节点的下标(从0开始)

1 -> 2 -> 3 -> 4 -> 5

坐标节点就是链表的中间节点

时间复杂度:O(n)

空间复杂度:O(1)

```

public ListNode middleNode(ListNode head) {

/**

* 先计算链表一共有多少个节点n

* n/2,得到中间节点的下标(从0开始)

* 1 -> 2 -> 3 -> 4 -> 5

* 坐标节点就是链表的中间节点

* */

int n=0;

ListNode p=head;

while (p!=null){

n++;

p=p.next;

}

int mid=n/2;

ListNode midNode=head;

for (int i = 0; i < mid; i++) {

midNode=midNode.next;

}

return midNode;

}

```

方法二:双指针

解题方法:

定义快慢两个指针,快指针每次移动2步,慢指针每次移动1步

注意:指针需要从头节点前开始移动,因此需要定义一个哑结点,快指针和慢指针都从哑节点开始

当快指针移动了2k步后,慢指针移动了k步

假设2k=n,k=n/2

当n为偶数时,慢指针的后续节点就是中间节点

当n为奇数时,慢指针就是中间节点

是否是偶数节点看快指针每次是否都能移动两步

时间复杂度:O(n)

空间复杂度:O(1)

```

public ListNode middleNode(ListNode head) {

/**

* 定义快慢两个指针,快指针每次移动2步,慢指针每次移动1步

* 注意:指针需要从头节点前开始移动,因此需要定义一个哑结点,快指针和慢指针都从哑节点开始

* 当快指针移动了2k步后,慢指针移动了k步

* 假设2k=n,k=n/2

* 当n为偶数时,慢指针的后续节点就是中间节点

* 当n为奇数时,慢指针就是中间节点

* 是否是偶数节点看快指针每次是否都能移动两步

* -1 -> 1 -> 2 -> 3 -> 4 -> 5 -> null

* -1 -> 1 -> 2 -> 3 -> 4 -> null

* */

if(head == null){

return null;

}

ListNode dummy = new ListNode(-1);

dummy.next=head;

ListNode slow=dummy;

ListNode fast=dummy;

ListNode midNode=null;

Boolean isEvent=true;

while (fast.next!=null){

slow=slow.next;

if(fast.next.next!=null) {

fast = fast.next.next;

} else{

fast=fast.next;

isEvent=false;

}

}

midNode = isEvent ? slow.next : slow;

return midNode;

}

```

方法三:双指针优化

解题方法:

定义快慢两个指针,快指针每次移动2步,慢指针每次移动1步

快指针和慢指针都从头节点开始移动

当快指针移动到链尾时,慢指针移动了k步,n>1

当n为偶数时,n-1必然是奇数

即快指针移动了2(k-1)+1步

此时快慢指针距离原点距离

快2(k-1)+1+1 简化 2k

慢k+1

即慢指针正好处于链表中间位置。

当n为奇数时,n-1必然是偶数

,快指针移动了2k步

此时快慢指针距离原点距离

2k+1

k+1

即慢指针正好处于链表中间位置

时间复杂度:O(n)

空间复杂度:O(1)

方法二的本质是下面的公式:

偶数

快2k

慢k

中间k+1

奇数

快2k-1

慢k

中间k

即快慢指针的初始位置+1就把公式统一了。

```

public ListNode middleNode(ListNode head) {

if(head == null){

return null;

}

ListNode slow=head;

ListNode fast=head;

while (fast!=null && fast.next!=null){

slow=slow.next;

fast = fast.next.next;

}

return slow;

}

```

相关推荐
青橘MATLAB学习4 分钟前
机器学习核心知识:从基础概念到关键算法
人工智能·算法·机器学习·逻辑回归·监督学习·梯度下降法·分类算法
zhangxueyi14 分钟前
Java实现快速排序算法
java·数据结构·算法
爱编程的鱼34 分钟前
C# 数据类型||C# 类型转换
java·算法·c#
Haohao+++36 分钟前
leetcode面试经典算法题——2
算法·leetcode·面试
蓝白咖啡38 分钟前
LinkedList<Integer> 常用方法通俗讲解
数据结构·算法·jave
coder77771 小时前
js逆向分享
javascript·爬虫·python·算法·安全
冠位观测者2 小时前
【Leetcode 每日一题 - 补卡】1534. 统计好三元组
数据结构·算法·leetcode
明月看潮生2 小时前
青少年编程与数学 02-016 Python数据结构与算法 25课题、量子算法
python·算法·青少年编程·量子计算·编程与数学
JNU freshman2 小时前
C. Robin Hood in Town思考与理解
算法
Net_Walke3 小时前
【C数据结构】 TAILQ双向有尾链表的详解
c语言·数据结构·链表