138. ランダムポインタによるリストのコピー
長さ n のリンク リストは、各ノードに追加のランダム ポインタが含まれるように指定されます。このポインタは、リスト内の任意のノードまたは null を指すことができます。
リストのディープコピーを作成します。ディープ コピーは正確に n 個の新しいノードで構成されている必要があります。各新しいノードの値は、対応する元のノードの値に設定されます。新しいノードの次のポインタとランダムなポインタは両方とも、元のリストとコピーされたリスト内のポインタが同じリスト状態を表すように、コピーされたリスト内の新しいノードを指す必要があります。新しいリスト内のポインタはいずれも、元のリスト内のノードを指してはなりません。
たとえば、元のリストに 2 つのノード X と Y があり、X.random --> Y である場合、コピーされたリスト内の対応する 2 つのノード x および y については、x.random --> y となります。
コピーしたリンクリストの先頭を返します。
リンク リストは、入出力では n 個のノードのリストとして表されます。各ノードは [val,random_index] のペアとして表されます。ここで、
val: Node を表す整数。val
random_index: ランダム ポインターが指すノードのインデックス (0 から n-1 の範囲)。ノードを指していない場合は null。
コードには、元のリンク リストの先頭のみが与えられます。
例 1:
入力: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
出力: [[7,null],[13,0], [11,4]、[10,2]、[1,0]]
例 2:
入力: head = [[1,1],[2,1]]
出力: [[1,1],[2,1]]
例 3:
入力: head = [[3,null],[3,0],[3,null]]
出力: [[3,null],[3,0],[3,null]]
制約:
- 0 <= n <= 1000
- − 1 0 4 < = ノード。val < = 1 0 4 -10^4 <= Node.val <= 10^4− 1 04<=ノード。_ _ _ v a l<=1 04
- Node.random が null であるか、リンクされたリスト内のノードを指しています。
From: LeetCode
Link: 138. ランダム ポインタを使用したリストのコピー
解決:
アイデア:
この問題の主な課題は、ノード間のランダムなポインタ関係を維持しながら、リンク リストのディープ コピーを作成することです。このソリューションでは、元のノードとそのコピーの間のマッピングを使用して、コピーされたリスト内の次のランダムなポインターが適切なノードを指すようにします。
手順:
1. ノードを数えます。
- ノードをコピーする前に、元のリストを調べてノードの数を数えます。このカウントは、マッピング構造にメモリを割り当てるのに役立ちます。
2. マッピング構造を初期化します。
- oldNodes と newNodes の 2 つの配列を使用します。
- oldNodes は元のノードへのポインタを保存します。
- newNodes は、対応するコピーされたノードへのポインターを格納します。
- 2 つの配列間の関係は、oldNodes 内の元のノードのインデックスが newNodes 内のコピーのインデックスと一致するということです。
3. ノードをコピーし、マッピング構造を塗りつぶします。
- 元のリストを再度調べて、ノードごとにそのコピーを作成します。
- 元のノードを oldNodes 配列に追加し、そのコピーを newNodes 配列に追加して、それらが同じインデックスにあることを確認します。
4. 次のランダムなポインターを確立します。
- 元のリストをもう一度調べます。
- コピーされたノードの次のポインターの場合:
- oldNodes 配列内で元のノードの次のポインターのインデックスを見つけます。
- 次に、このインデックスを使用して、コピーされたノードの次のポインターが newNodes 配列内の適切なノードを指すように設定します。
- 同様に、ランダム ポインタの場合は次のようになります。
- oldNodes 配列内で元のノードのランダム ポインターのインデックスを見つけます。
- 次に、このインデックスを使用して、コピーされたノードのランダム ポインタが newNodes 配列内の適切なノードを指すように設定します。
コード:
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head) {
if (head == NULL) return NULL;
struct Node* curr = head;
int count = 0;
// Count nodes
while (curr) {
count++;
curr = curr->next;
}
struct Node* oldNodes[count];
struct Node* newNodes[count];
curr = head;
int index = 0;
// 1. Copy nodes and fill our mapping structure
while (curr) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->val = curr->val;
newNode->next = NULL;
newNode->random = NULL;
oldNodes[index] = curr;
newNodes[index] = newNode;
curr = curr->next;
index++;
}
curr = head;
index = 0;
// 2. Copy next and random pointers using our mapping structure
while (curr) {
if (curr->next) {
int nextIndex = 0;
while (oldNodes[nextIndex] != curr->next) {
nextIndex++;
}
newNodes[index]->next = newNodes[nextIndex];
}
if (curr->random) {
int randomIndex = 0;
while (oldNodes[randomIndex] != curr->random) {
randomIndex++;
}
newNodes[index]->random = newNodes[randomIndex];
}
curr = curr->next;
index++;
}
return newNodes[0];
}