Given a non-empty, singly linked list with head node head
, return a middle node of linked list.html
If there are two middle nodes, return the second middle node.node
Example 1:git
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:github
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:數組
1
and 100
.
這道題給了一個鏈表,讓咱們找其中間結點。因爲鏈表不像數組,不能經過座標位置來直接訪問元素,而是隻能從頭結點開始,使用 next 指針來訪問以後的結點,爲了知道當前結點的位置,還得使用計數器來記錄。因爲在不知道鏈表的總長度以前,是沒法知道中間結點的位置的,那麼能夠首先遍歷一遍,統計出鏈表的長度,此時長度有了,除以2就是中間結點的位置了,再從頭遍歷一遍,就能夠找出中間結點的位置了,參見代碼以下:this
解法一:spa
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; } };
因爲鏈表沒法經過座標位置來訪問元素,但咱們能夠將全部的結點按順序存入到一個數組中,那麼以後就能夠直接根據座標位置來訪問結點了,參見代碼以下:指針
解法二:code
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 鏈表中找環的題,咱們介紹過快慢指針,就是兩個指針,慢指針一次走一步,快指針一次走兩步,那麼這裏當快指針走到末尾的時候,慢指針恰好走到中間,這樣就在一次遍歷中,且不須要額外空間的狀況下解決了問題,參見代碼以下:htm
解法三:
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
相似題目:
參考資料: