题目描述:
给定一个单链表 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
题目链接:
解题主要思路:
我一开始想到的是用数组存储ListNode*,然后利用指针来操作,但是该方法需要借助数组实现。后来可以先利用快慢指针找到链表的中点,将链表一分为二,再将尾部的链表逆序,最后将两个链表交替合并即可。
解题代码:
cpp
/**
* 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) {
if (head == nullptr || head->next == nullptr || head->next->next == nullptr) return;
// 快慢指针找中点
ListNode* slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
// 从slow后面的断开
ListNode* head2 = new ListNode(0);
// 逆序slow后面的节点,头插到head2
ListNode* cur = slow->next;
slow->next = nullptr;
while (cur) {
ListNode* next = cur->next;
cur->next = head2->next;
head2->next = cur;
cur = next;
}
// 合并两个链表
ListNode* ret = new ListNode(0);
ListNode* prev = ret;
ListNode* cur1 = head, *cur2 = head2->next;
while (cur1) {
// 先插入第一个链表,即长的链表
prev->next = cur1;
cur1 = cur1->next;
prev = prev->next;
// 再插入第二个链表
if (cur2) {
prev->next = cur2;
cur2 = cur2->next;
prev = prev->next;
}
else break;
}
delete ret;
delete head2;
}
};