题目思路比较直接:
1)把整个链表划分成2个等长的子链表,如果原链表长度为奇数,那么第一个子链表的长度多1。
2)翻转第二个子链表;
3)将两个子链表合并。
代码里有些变量可以省去,为了看起来逻辑清晰,还是保留了。整个链表遍历了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 *kp=head;
ListNode *mp=head;
while(kp!=NULL && kp->next!=NULL) //快慢指针遍历找到靠后的中间节点,保证前半段不小于后半段链表
{
kp=kp->next->next;
mp=mp->next;
}
ListNode *h1=head;
ListNode *h2=mp->next;
mp->next=NULL;
ListNode *preNode=NULL; //后半段链表的翻转reverse
ListNode *nextNode=NULL;
while(h2!=NULL)
{
nextNode=h2->next;
h2->next=preNode;
preNode=h2;
h2=nextNode;
}
h2=preNode;
while(h2!=NULL) //两个单链表的合并
{
ListNode *tmp1=h1->next;
ListNode *tmp2=h2->next;
h1->next=h2;
h2->next=tmp1;
h1=tmp1;
h2=tmp2;
}
}
};