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}.
题目的意思是要求对一个链表进行重新排序,如上面所示将 L0→L1→…→Ln-1→Ln, 重新排序之后变成 L0→Ln→L1→Ln-1→L2→Ln-2→…
思路: 可以看成是两个链表进行合并,现拆分 L0→Ln→L1→Ln-1→L2→Ln-2→… 变成:
L0 L1 L2 .......
Ln Ln-1 Ln-2 .....
所以我们可以将 L0→L1→…→Ln-1→Ln, 折半拆分,变成 L0 L1 L2 .....Ln/2 和 Ln/2 Ln/2+1 ....Ln
然后将后半部分进行逆置 ,变成L0 L1 L2 .......,Ln Ln-1 Ln-2 ..... 再将两链表合并
拆分过程在链表归并排序中曾遇到过 Sort List ,定义一快一慢指针,快的一次走两步,慢的一次走一步,遍历链表,最后慢的 的下一个节点为后半部分。
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode * reorderList(ListNode *head) {
if(head==NULL||head->next==NULL||head->next->next==NULL)
return head;
ListNode *fast,*showl;//定义fast和showl用来找到链表的中点
fast=head;
showl=head;
while(fast->next!=NULL&&fast->next->next!=NULL)
{
fast=fast->next->next;//fast一次走两步
showl=showl->next;//showl 一次走一步
}
// ListNode *halfafter=new ListNode()
ListNode *start,*pur,*q;
start=showl->next;//start表示 下一半节点的开始
//将以start开始的后半节点逆置
pur=start;
while(start!=NULL)
{
q=start;
start=start->next;
q->next=showl->next;
showl->next=q;
}
pur->next=NULL;
ListNode *p,*qur;
p=head; //前半部分第一个节点
q=showl->next; //后半部分第一个节点
showl->next=NULL;//断开链表
while(q!=NULL)
{
pur=p->next; //用来保存前半部分的下一个节点
qur=q->next; //用来保存后半部分的下一个节点
p->next=q;
q->next=pur;
p=pur;
q=qur;
}
return head;
}
};
原文:http://blog.csdn.net/yujin753/article/details/41988849