タイトル説明:
複雑なリンクリストをコピーするには、copyRandomList関数を実装してください。複雑なリンクリストでは、各ノードには次のノードへの次のポインタと、リンクリスト内の任意のノードまたは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]]
例4:
入力:head = []
出力:[]
説明:指定されたリンクリストは空(nullポインター)であるため、nullが返されます。
問題解決のアイデア:
この質問のアイデアは非常に賢いです。彼が提供したデータにはそれぞれ2つのデータがあり、2番目の数字は紛らわしいと思います。このデータは効果がなく、コードでこのデータを見つけることは不可能です。
したがって、問題を解決するときは、他の方法を使用してこのデータを置き換える必要があります。
- 最初に各ノードをコピーして、ノードの後ろに配置します
- このとき、元のリンクリスト内の各ノードのランダム性に従って、コピーされたノードのランダム性を見つけます。(このステップが鍵です)
- コピーしたノードを分離して
言うまでもなく、最初と3番目のステップは、ほぼ完全にコピーされた新しいノードであるため、 2番目のステップを取得する方法です。したがって、新しくコピーされたノードyのランダムは、元のノードxの次のランダムです。
上の図に示すように、BのランダムがAを指している場合、B1のランダムはA1を指している必要があります。
A1の方法は、B-> random-> nextであり、これはB1-> randomの値です。
コード:
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if(!head) return NULL;
Node *headx = head;
//将每个节点复制到他后面
while(headx)
{
auto x = new Node(headx->val);
x->next = headx->next;
headx->next = x;
headx = x->next;
}
//将另一个指针也复制一次
Node *heady = head;
while(heady && heady->next)
{
if(heady->random)
heady->next->random = heady->random->next;
heady = heady->next->next;
}
//将两个分离
Node *newhead = head->next;
Node *headz = head;
while(headz && headz->next)
{
Node *z = headz->next;
headz->next = z->next;
headz = z;
}
return newhead;
}
};