Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.
For example,
Given {1,2,3,4}
, reorder it to {1,4,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==NULL || head->next==NULL)
return;
ListNode* slow=head;
ListNode* fast=head;
//定位链表中间
while(fast->next!=NULL && fast->next->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;
}
ListNode* sHead=slow->next;
slow->next = NULL;//断开前后两部分
reverList(&sHead);
print(sHead);
mergeList(head, sHead);
}
private:
void print(ListNode* head)
{
while(head)
{
cout<<head->val<<" ";
head=head->next;
}
cout<<endl;
}
//一定要传递指针的指针,因为要修改传入的指针
void reverList(ListNode** pphead)
{
ListNode *head = *pphead; // -----------------1
if(head==NULL || head->next==NULL)
return;
ListNode* rHead = head ;
head=head->next;
rHead->next=NULL;
while(head)
{
ListNode* tmp = head->next;
head->next = rHead; // ----------------2
rHead=head;
head=tmp;
}
*pphead=rHead; // 一定要有这一句,不能因为1,2两句就觉得修改,head是个指针,*pphead的临时拷贝副本 (ListNode *head = *pphead),修改head指针的指向,只是修改了临时拷贝副本的指向,并没有修改*pphead本身的指向
}
void mergeList(ListNode* fHead, ListNode* sHead)
{
if(fHead==NULL || sHead==NULL)
return;
while(sHead)
{
ListNode* tmp = fHead->next;
fHead->next = sHead;
sHead=sHead->next; // 一定要写在这里,fHead->next->next=tmp; 的前面,不能写在3的位置,因为下一句修改了sHead->next
fHead->next->next=tmp;
//sHead=sHead->next; // ------------------3
fHead=tmp;
}
}
};