Leetcode|Reorder List

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mike_learns_to_rock/article/details/47159619

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

猜你喜欢

转载自blog.csdn.net/mike_learns_to_rock/article/details/47159619
今日推荐