算法系列-力扣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;

}

```

相关推荐
至乐活着1 小时前
深入解析跳表SkipList:原理、实现与性能优化实战
数据结构·算法·跳表·skiplist·java实现
Jerry2 小时前
LeetCode 383. 赎金信
算法
ai产品老杨2 小时前
H264 H265视频分析常见问题和排查清单
人工智能·算法·音视频
Jerry2 小时前
LeetCode 454. 四数相加 II
算法
可编程芯片开发3 小时前
基于CPS-SPWM链式STATCOM系统在电压不平衡环境下控制策略的simulink建模与仿真
算法
Jerry3 小时前
LeetCode 202. 快乐数
算法
hans汉斯4 小时前
基于改进交叉熵损失函数与Transformer的心电信号高风险分类研究
功能测试·深度学习·算法·yolo·目标检测·分类·transformer
Jerry4 小时前
LeetCode 349. 两个数组的交集
算法
YuK.W5 小时前
Leetcode100: 70.爬楼梯、118.杨辉三角、198.打家劫舍
java·算法·leetcode
随意起个昵称5 小时前
状压dp-基础题目2([USACO12MAR] Cows in a Skyscraper G)
c++·算法·动态规划