题目描述:
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln-1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
- 输入: head = [1,2,3,4]
输出: [1,4,2,3] - 输入: head = [1,2,3,4,5]
输出: [1,5,2,4,3]
解题思路:
寻找中间结点 + 链表逆转 + 合并链表
1.找到链表的中间结点,利用快慢指针法寻找中间结点
2. 将原链表的右半部分链表逆转
3. 将两链表合并`
/*
解题思路:
先找到中间结点,分割成两个新的链表,然后对右侧的链表进行反转,再重新连接两个链表即可
*/
//逆转链表
struct ListNode *reverse(struct ListNode *head)
{
if(head == NULL || head->next == NULL)
return head;
struct ListNode *newHead = reverse(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
void reorderList(struct ListNode* head){
if(head == NULL || head->next == NULL)
return head;
struct ListNode *left = head,*right = head;
while(right && right->next)
{
left = left->next;
right = right->next->next;
}
//此时left指向中间的结点
struct ListNode leftHead,rightHead; //使用两个新的头结点
leftHead.next = head;
rightHead.next = left->next;
left->next = NULL; //更新中间结点的后继结点
rightHead.next = reverse(rightHead.next); //反转右侧链表
left = leftHead.next;
right = rightHead.next; //更新指针位置
struct ListNode *p=&leftHead;
while(left && right)
{
p->next = left;
left = left->next;
p=p->next;
p->next = right;
right=right->next;
p=p->next;
}
p->next = left?left:right;//指针p的后继指向 left 和 right 中不空的那个结点
}