题目描述:
将给定的单链表 L: L0→L1→…→Ln−1→Ln
重新排序为:L0→Ln→L1→Ln−1→L2→Ln−2→…
要求使用原地算法,不能改变节点内部的值,需要对实际的节点进行交换。
例如:
对于给定的单链表{1,2,3,4},将其重新排序为{1,4,2,3}.
思路:
1.快慢指针寻找链表中间节点;
2.原地逆序后半段链表;
3.合并顺序的前半段和逆序的后半段,完成链表重排序。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode *head) {
if(head==nullptr||head->next==nullptr||head->next->next==nullptr)
return;
ListNode *fast=head,*slow=head;
while(fast->next!=nullptr&&fast->next->next!=nullptr){
fast=fast->next->next;
slow=slow->next;
}//快慢指针寻找链表中间节点,循环结束之后,slow指针指向中间结点
fast=slow->next;//记录fast为后半段第一个结点
slow->next=nullptr;//
while(fast){//将后半段原地逆序
ListNode* tmp=fast->next;
fast->next=slow->next;
slow->next=fast;
fast=tmp;
}
//合并前半段和逆序的后半段
ListNode *p=head;//左起第一个
ListNode *q=slow->next;//右起第一个
while(p!=nullptr&&q!=nullptr){
slow->next=q->next;//slow->next每次记录当前的下一个位置
q->next=p->next;//将当前结点q依次插入前半段
p->next=q;
p=q->next;//当前节点完成之后左起第一个指针后移两步
q=slow->next;//右起第一个指针变为刚刚记录的右起第一个的下一个结点
}
}
};