leetcode138.ランダムポインタを使用してリンクリストをコピーする

長さnのリンクリストが与えられます。各ノードには、リンクリスト内の任意のノードまたは空のノードを指すことができる追加のランダムポインタランダムが含まれています。

このリンクリストのディープコピーを作成します。ディープコピーは、正確にn個の新しいノードで構成する必要があります。ここで、各新しいノードの値は、対応する元のノードの値に設定されます。新しいノードの次のポインターとランダムポインターも、コピーされたリンクリストの新しいノードを指す必要があります。これにより、元のリンクリストとコピーされたリンクリストのこれらのポインターは、同じリンクリストの状態を表すことができます。

コピーされたリンクリスト内のどのポインタも、元のリンクリスト内のノードを指してはなりません。
ここに画像の説明を挿入

アイデア

1.元のリンクリストのすべてのノードをコピーし、新しいノードを元のノードの後ろに挿入します。

ここに画像の説明を挿入
まず、curの位置に移動するたびに、最初に新しいノードのコピーを作成します。copy-> next = cur-> next、cur-> next = copy
ここに画像の説明を挿入
次に、元のリンクリストは引き続き逆方向に移動します。cur= copy ->次に、すべてのノードが複製されるまで上記の操作を繰り返します
ここに画像の説明を挿入

2.元のノードのランダムに従って、コピーされたノードのランダムを見つけます

元のリンクリストの最初のノード、7-> random = NULL、次にコピーノード7->randomもNULLです

ここに画像の説明を挿入

元のリンクリストの2番目のノードである13->random= 7の場合、コピーノード13-> randomはコピーノード7であり、これは元のリンクリストのノード13->random->nextです。

copyNode = cur-> next、copyNode-> random = cur-> random-> next、
元のリンクリストは引き続き逆方向に移動します。cur= copyNode-> next;
ここに画像の説明を挿入

元のリンクリストの3番目のノードである11->random= 1の場合、コピーノード11-> randomはコピーノード1であり、これは元のリンクリストのノード11->random->nextです。
ここに画像の説明を挿入

同様に、次の図に示すように、残りのレプリカノードのランダムを取得できます。
ここに画像の説明を挿入
終了条件はcur==NULLです。
ここに画像の説明を挿入

3.コピーノードを解き、元のリンクリストを復元します

初期条件として、コピーリンクリストのヘッドノードとテールノードをそれぞれ表す2つのポインタを
ここに画像の説明を挿入
定義します。次に、コピー= cur-> next、next = copy-> nextの2つのノードポインタを定義し、以下のリンクリストを開きます。

リンクリストの最初のノードをコピーします。copyHeadはヘッドノードの位置を記憶し、変更しません。copyHead= copyTail = copy、cur-> next = next
ここに画像の説明を挿入

curは引き続き逆方向に進み、cur = cur-> next
ここに画像の説明を挿入
copyTail-> next = copy、copyTail=copyなどになります
ここに画像の説明を挿入

ここに画像の説明を挿入

cur==NULLになるまでループが終了します

ここに画像の説明を挿入

分割完了
ここに画像の説明を挿入

struct Node* copyRandomList(struct Node* head)
{
    
    
    //1.复制链表,并插入到原链表中
    struct Node* cur = head;

    while (cur != NULL)
    {
    
    
        //创建新结点
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));

        if (copy == NULL)
        {
    
    
            exit(-1);
        }

        copy->val = cur->val;

        //新结点插入到原结点和下一个结点之间
        copy->next = cur->next;

        cur->next = copy;

        cur = copy->next;
    }

    //2.根据原链表中原结点的random,找到复制结点的random

    cur = head;

    while (cur != NULL )
    {
    
    
    	//复制链表向后走
        struct Node* copyNode = cur->next;

        if (cur->random == NULL)
        {
    
    
            copyNode->random = NULL;
        }
        else
        {
    
    
            copyNode->random = cur->random->next;
        }
        //原链表继续向后走
        cur = copyNode->next;
    }
    
    //3.取下新链表,恢复原链表
    cur = head;
 
 	//定义复制链表的头结点、尾结点
    struct Node* copyHead = NULL;
    struct Node* copyTail = NULL;

	while (cur != NULL)
    {
    
    
    	//定义两个指针变量,更清晰
        struct Node* copy = cur->next;
        struct Node* next = copy->next;

        if (copyTail == NULL)
        {
    
    
            //复制链表头结点
            copyTail = copyHead = copy;
        }
        else
        {
    
    
            //复制链表向后走
            copyTail->next = copy;
            copyTail = copy;
        }
		
		//恢复原链表
        cur->next = next;
        
		//原链表继续向后走
        cur = next;
    }
    
  //while (cur != NULL )
    //{
    
    
    //    if (cur == head)
    //    {
    
    
    //        //新链表头结点
    //        copyHead = copyTail = cur->next;
    //    }
    //    else
    //    {
    
    
    //        copyTail->next = cur->next;
    //        copyTail = copyTail->next;
    //    }
    //    cur->next = copyTail->next;
    //    cur = cur->next;
    //}

    return copyHead;
}

おすすめ

転載: blog.csdn.net/weixin_42836316/article/details/122370486