Leetcode|Reorder List
阿新 • • 發佈:2018-11-14
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}.
解法1:笨重的方法 超時O(n^2)
就是不斷從前往後遍歷到頭兒,每次遍歷的長度都減小2個。
void reorderList(ListNode* head) {//笨重的方法 遍歷了很多次!超時!!!
if (!head||!head->next||!head->next->next) return;
ListNode *l1=head,*l2=head->next,*r1=head->next,*r2=r1->next;
//l1被插入節點的前個節點 l2被插入節點的後一個節點 r1搜尋節點中慢節點 r2搜尋節點快節點找到最後一個節點
//r2->next=NULL代表r2位Ln,Ln-1,...... r1代表r2前一個節點
while(r2){
for(;r2->next ;r1=r2,r2=r2->next);
l1->next=r2;
r2->next=l2;
r1->next=NULL;
l1=l2;
l2=l2->next;
if(l2==NULL) return;
r1=l2;
r2=r1->next;
}
}
解法2:時間O(n) 空間O(1)
找到中點,然後翻轉後半部分。然後合併兩個連結串列。注意合併截止條件。(類似 判斷迴文連結串列的題目)
//找出後一半 反轉然後變成兩個連結串列的合併
public:
void reorderList(ListNode* head){
if(!head) return;
ListNode* pMid=findMiddle(head);
ListNode* pNew=reverseList(pMid);
while(head->next&&pNew->next){
ListNode* nextNew=pNew->next;
pNew->next=head->next;
head->next=pNew;
head=pNew->next;
pNew=nextNew;
}
}
private:
ListNode* findMiddle(ListNode* head){
ListNode *slow=head, *fast=head;
while(fast&&fast->next){
fast=fast->next->next;
slow=slow->next;
}
return slow;//奇數正好在中間,偶數正好在後一段開頭;
}
//翻轉連結串列 魔板
ListNode* reverseList(ListNode* head){
ListNode* p=NULL;
while(head){
ListNode* q=head->next;
head->next=p;
p=head;
head=q;
}
return p;
}