876. 链表的中间结点
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
输入:[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.
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/middle-of-the-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
最简单的想法是遍历两次,第一次求出链表长度,第二次删除中间节点,但是显然这中这与考察的目的不符,而且效率极低。
那么有没有办法在一次遍历就完成操作呢?联系题目下双指针的tag想到利用快慢指针来完成这一操作。
令快指针每次走两格,而慢指针顺序遍历,这样当快指针遍历结束后真好慢指针到达中央位置,代码如下:
class Solution {
public ListNode middleNode(ListNode head) {
ListNode fast=head,slow=head;
while(fast!=null&&fast.next!=null) //此处必须判断fast和fast->next是否为空,不然出现null.next报错。
{
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
}
19. 删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
本题最初的想法还是直接求长度然后遍历,但是联想到之前看到的一篇限流相关文章中提到的滑动窗口,突然意识到可以利用这种方法来完成。
即首先初始时设定fast指针比slow指针快n个元素,那么当fast指针到最后一个元素时,slow真好说想要删除节点的前驱进行删除即可。
注意:当n的长度>=n时,即删除首节点,此时直接操作slow节点即可。
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode fast=head,slow=head;
for(int i=0;i<n&&fast!=null;i++)
{
fast=fast.next;
}
if(fast==null) //如果fast==null,说明此时需要删除的节点即为首节点
{
head=head.next;
}
else{
while(fast.next!=null)
{
fast=fast.next;
slow=slow.next;
}
slow.next=slow.next.next;
}
return head;
}
}
标签:结点,slow,Day5,head,fast,next,leetcode,指针
From: https://www.cnblogs.com/zz-gy/p/17051580.html