Leetcode|Reorder List

来源:互联网 发布:c语言添加线程 编辑:程序博客网 时间:2024/06/05 07:01

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