876. Middle of the Linked List

Given a non-empty, singly linked list with head node head, return a middle node of linked list.

If there are two middle nodes, return the second middle node.

Example 1:

Input: [1,2,3,4,5]
Output: Node 3 from this list (Serialization: [3,4,5])
The returned node has value 3.  (The judge's serialization of this node is [3,4,5]).
Note that we returned a ListNode object ans, such that:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, and ans.next.next.next = NULL.

Example 2:

Input: [1,2,3,4,5,6]
Output: Node 4 from this list (Serialization: [4,5,6])
Since the list has two middle nodes with values 3 and 4, we return the second one.

Note:

  • The number of nodes in the given list will be between 1 and 100.

这道题给了一个链表,让我们找其中间结点。由于链表不像数组,不能通过坐标位置来直接访问元素,而是只能从头结点开始,使用 next 指针来访问之后的结点,为了知道当前结点的位置,还得使用计数器来记录。由于在不知道链表的总长度之前,是无法知道中间结点的位置的,那么可以首先遍历一遍,统计出链表的长度,此时长度有了,除以2就是中间结点的位置了,再从头遍历一遍,就可以找出中间结点的位置了,参见代码如下:
解法一:

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        ListNode *cur = head;
        int cnt = 0;
        while (cur) {
            ++cnt;
            cur = cur->next;
        }
        cnt /= 2;
        while (cnt > 0) {
            --cnt;
            head = head->next;
        }
        return head;
    }
};

由于链表无法通过坐标位置来访问元素,但我们可以将所有的结点按顺序存入到一个数组中,那么之后就可以直接根据坐标位置来访问结点了,参见代码如下:
解法二:

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        vector<ListNode*> vec(100);
        int cur = 0;
        while (head) {
            vec[cur++] = head;
            head = head->next;
        }
        return vec[cur / 2];
    }
};

上面两种方法一个多用了时间,一个多用了空间,其实都不是最优的解法,最好的方法其实是使用快慢指针来做。在之前那道 Linked List Cycle 链表中找环的题,我们介绍过快慢指针,就是两个指针,慢指针一次走一步,快指针一次走两步,那么这里当快指针走到末尾的时候,慢指针刚好走到中间,这样就在一次遍历中,且不需要额外空间的情况下解决了问题,参见代码如下:
解法三:

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        ListNode *slow = head, *fast = head;
        while (head && head->next) {
            slow = slow->next;
            head = head->next->next;
        }
        return slow;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/876

类似题目:

Linked List Cycle

参考资料:

https://leetcode.com/problems/middle-of-the-linked-list/

https://leetcode.com/problems/middle-of-the-linked-list/discuss/154619/C%2B%2BJavaPython-Slow-and-Fast-Pointers

https://leetcode.com/problems/middle-of-the-linked-list/discuss/155148/Java-O(n)-time-and-O(1)-space-solution-without-using-fastslow-pointer

LeetCode All in One 题目讲解汇总(持续更新中…)


转载请注明来源于 Grandyang 的博客 (grandyang.com),欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 grandyang@qq.com

💰


微信打赏


Venmo 打赏

(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,试运营期间前五十位可享受半价优惠~)

×

Help us with donation