Problem: 876. 链表的中间结点
方法一:额外数组
思路
遍历链表将其转换成数组,获取链表长度n,中间节点所在位置为 ⌊ n 2 ⌋ \left\lfloor \frac{n}{2} \right\rfloor ⌊2n⌋,直接访问数组获取值。
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
vector<ListNode*> v;
while(head){
v.push_back(head);
head = head->next;
}
return v[v.size()/ 2];
}
};
方法二:两次遍历
思路
遍历一次链表获取链表长度n,中间节点所在位置为 ⌊ n 2 ⌋ \left\lfloor \frac{n}{2} \right\rfloor ⌊2n⌋
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
int n = 0;
ListNode* cur = head;
while(cur){
cur = cur->next;
n++;
}
cur = head;
for(int i = 0; i < n/2; i++){
cur = cur->next;
}
return cur;
}
};
复杂度
- 时间复杂度:
O ( n ) O(n) O(n)
- 空间复杂度:
O ( n ) O(n) O(n)
方法三:双指针(快慢指针)
思路
设置两个指针分别为slow和fast,slow每次走一步,fast每次走两步。当快指针走到结束时,慢指针所指的即为中间位置。
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* slow, *fast;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
};
复杂度
- 时间复杂度:
O ( n ) O(n) O(n)
- 空间复杂度:
O ( 1 ) O(1) O(1)