zoukankan      html  css  js  c++  java
  • [LeetCode] 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](https://www.cnblogs.com/grandyang/p/4137187.html) 链表中找环的题,我们介绍过快慢指针,就是两个指针,慢指针一次走一步,快指针一次走两步,那么这里当快指针走到末尾的时候,慢指针刚好走到中间,这样就在一次遍历中,且不需要额外空间的情况下解决了问题,参见代码如下:
    解法三:
    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 题目讲解汇总(持续更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)
  • 相关阅读:
    尚学堂 JAVA DAY12 概念总结
    A new classification algorithm recommendation method based on link prediction
    MLE & MAP
    Performance Measurement
    Stacking
    SVM
    I/O Multiplexing
    Bomb Lab
    ABOUT
    题目集概况 题目列表 提交列表 排名 共 60 分 编程题 (共 60 分) PAT 线上测试赛真题(2020-05-01)
  • 原文地址:https://www.cnblogs.com/grandyang/p/10817408.html
Copyright © 2011-2022 走看看