刷题系列之876. 链表的中间结点

121 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

前言

题目来源

leetcode.cn/problems/mi…

题目介绍

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

image.png

题目分析

审查题目中的关键词,非空单链表、中间结点,所以我们应该先回想到链表的定义。

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表通常由一连串节点组成,每个节点包含该节点的数据和指向上一节点或者下一节点的引用(链接)。

用一个java对象来表示就是

 * 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) {
         ArrayList<ListNode> listNode=new ArrayList<ListNode>();
          while (head != null) {
            listNode.add(head);
            head = head.next;
        }
        int n=listNode.size();
        return listNode.get(n/2);


    }
}

如上代码,先定义一个集合存储我们的节点,然后while循环我们的参数头节点,循环一个后,把next下一个又重新赋值给head,直到head不为空,说明节点已经没有下一个了。

这时候循环已经结束了,那么就取集合的中间下标的值就好了,即n/2,假如n=5,那么n就等于2,即集合的第三个值就是我们所求的结果。

image.png

image.png

官方答案验证分析

class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode[] A = new ListNode[100];
        int t = 0;
        while (head != null) {
            A[t++] = head;
            head = head.next;
        }
        return A[t / 2];
    }
}

官方的做法其实和我想的用集合存储是一样的,不过官方这里用了一个数组存储起来,每次遍历往里面加1,设定对应下标的值,然后取中间的值。同时还有很多其他解答方法,相对来说我觉得这种比较好理解。

class Solution {
    public ListNode middleNode(ListNode head) {
        ListNode slow = head, fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
}

这是另外一种做法,用两个指针 slow 与 fast 一起遍历链表。slow 一次走一步,fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间。这个思路也是非常的好。

总结

这道题相对来说难度稍微增加了一点,但是理解好链表的结构,还是可以做出来的。