题目
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln-1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入: head = [1,2,3,4]
输出: [1,4,2,3]
示例 2:
输入: head = [1,2,3,4,5]
输出: [1,5,2,4,3]
提示:
链表的长度范围为 [1, 5 * 104]
1 <= node.val <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reorder-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
链表模拟:
- 快慢指针法找到链表的中间位置,从中间位置开始分成两个链表,如果是奇数个结点应该是
[1,2,3,4,5]
分成[1,2,3]
和[4,5]
,偶数个结点就对半分开 - 把后面那个链表逆序,
[4,5]
变成[5,4]
- 尾插法轮流插入两个链表的结点,先 1,再 5,最后是
[1,5,2,4,3]
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
C++ 代码
/**
* 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:
void reorderList(ListNode* head) {
ListNode* quick = head;
ListNode* slow = head;
while (quick->next && quick->next->next) {
slow = slow->next;
quick = quick->next->next;
}
if (slow == head)
return;
ListNode* anotherHead = slow->next;
slow->next = nullptr;
reverseList(anotherHead);
ListNode* p = head;
ListNode* q = anotherHead;
while (q) {
ListNode* nextP = p->next;
ListNode* nextQ = q->next;
q->next = nextP;
p->next = q;
p = nextP;
q = nextQ;
}
}
void reverseList(ListNode*& head) {
if (!head)
return;
ListNode* newHead = new ListNode(0);
ListNode* p = head;
while (p) {
ListNode* q = p->next;
p->next = newHead->next;
newHead->next = p;
p = q;
}
head = newHead->next;
delete newHead;
}
};