1. 程式人生 > >leetcode138-複製帶隨機指標的連結串列

leetcode138-複製帶隨機指標的連結串列

方法一:利用map,空間複雜度O(N)

class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {
        if(head==NULL)
            return NULL;
        //先進行淺拷貝
        //先設定一個哨兵節點,方便直接從頭拷貝
         RandomListNode *header=new  RandomListNode(-1);
         RandomListNode *p=header;
         RandomListNode *q=head;
         map<RandomListNode*,RandomListNode*> m;
        while(q){//拷貝next指標
              RandomListNode *tmp=new RandomListNode(q->label);
              p->next=tmp;
              m[q]=tmp;
              p=p->next;
              q=q->next;
        }
        //拷貝random指標
        p=header->next;
        q=head;
        while(q){
            p->random=m[q->random];
            q=q->next;
            p=p->next;
        }
        return header->next;
    }
};

方法二:將每個節點都複製一遍,然後拷貝隨機指標:副本節點的隨機指標是原節點的隨機指標的下一個節點;

空間複雜度為O(1)

class Solution {

public:

    RandomListNode *copyRandomList(RandomListNode *head) {

        if(head==NULL)

            return NULL;

        //先複製每一個節點,如原來是1->2->3->4,複製後變為1->1'->2->2'->3->3'->4->4'

        RandomListNode *p=head;

        while(p){

            RandomListNode *tmp=new RandomListNode(p->label);

            tmp->next=p->next;

            p->next=tmp;

            p=p->next->next;//走兩步,跨過新加入的節點     

        }

        //複製Random指標

        p=head;

        RandomListNode *q=head->next;

        while(p){

            if(p->random)

            q->random=p->random->next;

            p=p->next->next;//注意,此處要走兩步

            if(q->next)

            q=q->next->next;//注意,此處要走兩步

        }

        //分離兩個連結串列:即分為1->2->3->4和1'->2'->3'->4'

        p=head;

        q=head->next;

        RandomListNode *newHead=q;

        RandomListNode *tmp1=NULL;

        RandomListNode *tmp2=NULL;

         

        while(p){

            tmp1=p->next->next;

            if(q->next==NULL)

                break;//1->1'的情況在此退出(連結串列遍歷到最後兩個節點時也從此處退出)

            tmp2=q->next->next;//此處:連結串列至少有4個節點1->1'->2->2'

            p->next=tmp1;

            q->next=tmp2;

            p=p->next;

            q=q->next;

            tmp1=tmp1->next->next;//連結串列至少有4個節點1->1'->2->2',所以可以保證tmp1往後移動一次

            if(tmp2->next)

                tmp2=tmp2->next->next;

            else

                tmp2=NULL;//即tmp2已經是連結串列最後一個節點,此時會在下次一進入while時,從break處退出(q->next==NULL)

        }

        p->next=NULL;

        return newHead;

    }

};