[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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM