Given a singly linked list L: L 0→L 1→…→L n-1→L n,
reorder it to: L 0→L n →L 1→L n-1→L 2→L n-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}.
反轉以后的鏈表是,從左往右是,node0->noden->node1->nodenn-1->.....,首先想到是將鏈表L按照這個規律重新賦值一遍,但題中說不能改變結點的值;然后想到將鏈表反轉然后重新連接起來,如1->2->3->4,

按虛線那樣走,形成1->4->2->3->3->2->4->1,若是結點的值都不相同,則遇到相同時,就可以斷開形成,若是有相同,可先統計結點的個數,然后判斷終止條件。這樣就需要新建一個鏈表。所以想到將鏈表一分為二,反轉后半段,然后重新連接起來,依舊是1->2->3->4,

這樣思路就出來了,分三步走,第一步,將鏈表一分為二,用到快慢指針;第二步,反轉第二部分,反轉鏈表是很重要的根基;第三步,將兩鏈表接起來。參考了JustDoIt的博客。
使用快慢指針將鏈表分成兩段,采用這種方式會導致在鏈表結點個數為奇數的情況下,后半段的個數比前半段多一個。前半段一preSlow維結束,后半段一slow開始。所以在第三步將兩子鏈表連接起來的時候,要注意判斷反轉以后以newBeg開始的后半段是否已經結束,沒有,則連接上剩余部分即可。

針對反轉鏈表,要認真的理解,關鍵是反轉以后,要在新的鏈表結尾加上next=NULL。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 void reorderList(ListNode *head) 12 { 13 if(head==NULL||head->next==NULL) 14 return; 15 //分成兩段 16 ListNode *preSlow=NULL; 17 ListNode *slow=head,*fast=head; 18 while(fast&&fast->next) 19 { 20 preSlow=slow; 21 slow=slow->next; 22 fast=fast->next->next; 23 } 24 preSlow->next=NULL; //前半段 25 26 //反轉后半段 27 ListNode *newBeg=slow; 28 ListNode *last=newBeg->next; 29 while(last) 30 { 31 ListNode *temp=last->next; 32 last->next=newBeg; 33 newBeg=last; 34 last=temp; 35 } 36 slow->next=NULL; 37 38 //合並 39 fast=head; 40 preSlow=NULL; 41 while(fast) //注:以前半段為條件 42 { 43 ListNode *tem=newBeg->next; 44 newBeg->next=fast->next; 45 fast->next=newBeg; 46 fast=newBeg->next; 47 preSlow=newBeg; 48 newBeg=tem; 49 } 50 if(newBeg !=NULL) //因節點個數為奇數時,后段比前段多一個,所以最后要判斷 51 preSlow->next=newBeg; 52 } 53 };
