题目链接:复制带随机指针的链表
描述:
若要实现一个链表的复制那就很方便,但本题给每个节点增加了一个额外的随机指针random,该指针可以指向链表中的任何节点或空节点,意思就是,原链表中每一个节点的random都确定的指向了原链表中的任何节点或者空节点,而拷贝之后的链表中每一个节点的random也要对应于原链表指向拷贝链表中相同位置的节点,如上图:原链表第二个节点中的random指向了第一个节点的位置,所以拷贝之后的链表的第二个节点也要指向拷贝链表的第一个节点
关键就在于如何处理拷贝链表中每一个节点的random指针
思路1:可以先遍历原链表的每一个节点,然后依次开辟拷贝节点,并放入相应的数据再依次链接起来,先不处理拷贝节点中的random;拷贝链表其余部分都处理完了,再循环原链表,找每一个节点中random的指向关系,再在拷贝链表循环每一个节点依次找到各个节点中random的指向关系;这种思路的时间复杂度为:O(N*N),时间复杂度太大;所以就需要另外一种取巧的方法
思路2:
第一步:遍历原链表,在原链表的每个节点之间插入上一个节点的拷贝节点,然后再链接起来
第二步:遍历新的链表,如下图可以看出,先判断每个拷贝节点的上一个节点的random是否为NULL,若为NULL则拷贝节点的random也为空;若不为空则拷贝节点的random可通过它上一个节点的random指向的节点下一个节点找到
第三步:断开拷贝节点与原链表节点之间的链接关系,再让拷贝节点依次链接起来,同时也可以恢复原链表的链接关系
struct Node* copyRandomList(struct Node* head) {
struct Node* cur = head;
while(cur)
{
struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
newnode->val = cur->val;
newnode->next = cur->next;
cur->next = newnode;
cur = cur->next->next;
}
cur = head;
while(cur)
{
struct Node* newnode = cur->next;
if(cur->random == NULL)
{
newnode->random = NULL;
}
else
{
newnode->random = cur->random->next;
}
cur = newnode->next;
}
cur = head;
struct Node* copyHead = NULL, *copyTail = NULL;
while(cur)
{
struct Node* copy = cur->next;
struct Node* next = copy->next;
cur->next = next;
if(copyTail == NULL)
{
copyHead = copyTail = copy;
}
else
{
copyTail->next = copy;
copyTail = copyTail->next;
}
cur = next;
}
return copyHead;
}