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