1. 程式人生 > >Leetcode|Reorder List

Leetcode|Reorder List

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;
    }