💯💯💯
⏰.链表深度拷贝
深度拷贝指的是将该链表上每个结点都拷贝过来,链接形式是与原链表一模一样。
但要注意的是,拷贝的链表的链接形式虽然跟原链表一样,但它们的地址都是不同的,拷贝的链表中的指针都不应该指向原链表中的结点。
而解答本题的思路就是:
1.在每个结点的后面生成自己的拷贝结点
2.处理每个拷贝结点的random
3.将所有拷贝结点拿下来,尾插形成新的链表
4.恢复原链表链接关系
🕑生成拷贝结点
//1.在每个结点的后面生成拷贝结点
struct Node* cur = head;//利用cur进行遍历,不使用head遍历
while (cur)
{
struct Node* next = cur->next;//记录后面结点的位置
struct Node* copy = (struct Node*)malloc(sizeof(struct Node));//开辟一个结点出来
copy->val = cur->val;//将原结点的数据拷贝过去
//cur copy next现在就是要求这个样子,cur第一个结点,copy要插在cur和next在中间
cur->next = copy;
copy->next = next;
//插入结点
cur = next;//迭代操作
}
🕒处理random
//2.处理每个拷贝结点的random
cur = head;//将cur重新指回头结点
while (cur)
{
struct Node* copy = cur->next;//记录每个拷贝结点的位置
if (cur->random == NULL)//如果原结点的random为NULL
{
copy->random = NULL;//则拷贝结点的random也为NULL
}
else
{
copy->random = cur->random->next;//否则拷贝结点的random就等于原结点random的next。
}
cur = cur->next->next;//cur每次要走两步,因为这样才可以每次都走到原结点上去,然后原结点的next就是拷贝结点
}
🕓解下拷贝结点
//3.解下拷贝结点,恢复原来结点链接
cur = head;//使cur重新指向头结点
struct Node* copyhead = NULL, * tail = NULL;//因为拷贝结点需要尾插成一条链表,需要头结点和找尾操作
while (cur)
{
//解下拷贝结点就是把结点拿下来尾插.尾插需要头指针尾指针
struct Node* copy = cur->next;//记录每个拷贝结点
struct Node* next = copy->next;//记录每个原来结点
if (copyhead == NULL)//一开始新链表头结点是空所以需要将第一个拷贝结点赋值过去
{
copyhead = tail = copy;
}
else
{
tail->next = copy;//接下来才是真正的尾插,将拷贝结点尾插到tail结点的next上去
tail = tail->next;//tail结点每次都需要更新,以便找尾
}
//恢复链接关系
cur->next = next;//next记录的是每个copy结点的下一个那就是原结点,原结点与cur链接恢复原来链接关系
//迭代
cur = next;
}
⏰.完整代码
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head)
{
//1.在每个结点的后面生成拷贝结点
struct Node* cur = head;
while (cur)
{
struct Node* next = cur->next;
struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
copy->val = cur->val;
//cur copy next
cur->next = copy;
copy->next = next;
//插入结点
// 迭代
cur = next;
}
//2.处理每个拷贝结点的random
cur = head;
while (cur)
{
struct Node* copy = cur->next;
if (cur->random == NULL)
{
copy->random = NULL;
}
else
{
copy->random = cur->random->next;
}
cur = cur->next->next;
}
//3.解下拷贝结点,恢复原来结点链接
cur = head;
struct Node* copyhead = NULL, * tail = NULL;
while (cur)
{
//解下拷贝结点就是把结点拿下来尾插.尾插需要头指针尾指针
struct Node* copy = cur->next;
struct Node* next = copy->next;
if (copyhead == NULL)
{
copyhead = tail = copy;
}
else
{
tail->next = copy;
tail = tail->next;
}
//恢复链接关系
cur->next = next;
//迭代
cur = next;
}
return copyhead;
}