「图解大厂面试高频算法题」链表专题-链表的中间结点(快慢指针)

「图解大厂面试高频算法题」链表专题-链表的中间结点(快慢指针)

PS: 本文为「图解大厂面试高频算法题」专题,主旨是根据“二八法则”的原理,以付出20%的时间成本,获得80%的刷题的收益,让那些想进互联网大厂的人少走些弯路。

PS: 欢迎关注我获取更多大厂面试总结。

原题链接: https://leetcode-cn.com/problems/middle-of-the-linked-list/

PS: 这道题的解法是很多中等和困难难度题的基础,希望大家能熟练掌握。本文还会举一反三,给出常见的变种题目,这些题目都是大厂高频面试题。

题目介绍

给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。

示例1

输入:[1,2,3,4,5]
输出:此列表中的结点 3
解释:返回的结点值为 3 。

示例2

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

题目解答

方法一:计数法

思路和算法

最简单的解法就是先遍历整个链表一次,记录节点数为N,节点数不管是基数还是偶数,我们只要在链表头节点遍历N/2次就得到了链表的中间节点。

参考代码
/**
 * 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; }
 * }
 */


class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode node = head;
        int N = 0;
        while (node != null) {
            N++;
            node = node.next;
        }
        int count = N / 2;
        while (count > 0) {
            head = head.next;
            count--;
        }
        return head;
    }
}
复杂度分析

n 是链表的长度

  • 时间复杂度:O(n),我们需要遍历两次链表;
  • 空间复杂度:O(1)。

方法二:快慢指针

思路和算法

比较经典的做法是,使用两个指针变量,刚开始都位于链表的第 1 个结点,慢指针一次只走 1 步,快指针一次只走 2 步。快指针走过的节点数量永远是慢指针的二倍。这样当快指针走完的时候,慢指针就来到了链表的中间位置。

图解

其中绿色指针为慢指针,每次迭代只走一个节点,蓝色指针为快指针,每次迭代走两个节点

初始状态

在这里插入图片描述

迭代一次之后

在这里插入图片描述

迭代两次之后

这时快指针到达了最后一个节点,算法停止迭代了,而慢指针正好到达了中间节点,
因为这个例子的链表有5个节点,为基数,所以慢指针最终恰好指向了中间节点。
在这里插入图片描述

迭代三次之后

我们看一下如果链表节点数为偶数,会是什么样。
这时快指针指向了null,算法停止迭代了,而慢指针正好到达了靠右的中间节点,
在这里插入图片描述

参考代码
/**
 * 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; }
 * }
 */
public class Solution {
    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;
    }
}
复杂度分析

n 是链表的长度

  • 时间复杂度:O(n),fast指针需要遍历一次链表,因此最多走 n 步;
  • 空间复杂度:O(1)。

面试tips

在面试中如果碰见了这道题,只写出计数法是不会加分的,面试官其实就想考察你快慢指针的用法。

举一反三

快慢指针思想还可以解决很多链表相关的题目,这些题目在大厂面试中很常见
「图解大厂面试高频算法题」148. 链表算法-排序链表
「图解大厂面试高频算法题」160. 链表算法-相交链表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知春路金刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值