
这道题要求将整个链表进行深拷贝,新链表中不包含任何原链表的节点,但是新链表中各个节点存储的值和各个节点的指向关系需要和原链表一模一样。我的思考过程如下:
1.新链表中的每一个节点的创建必须用new
关键字来创建,而不能只是简单的拷贝赋值;
2.由于ramdom
指针的随机性,A -> random
可能指向nullptr
,也可能指向A
之后的某个节点,也有可能指向A
之前的某个节点,也有可能指向自己,在构造链表的过程中,完全有可能出现A -> random
对应的节点还没构造出来的情况,此外,按照random
指针遍历链表可能出现有环的情况,从而导致无限循环。
3.要想遍历链表的所有节点,只能通过next
指针进行遍历,因此在构造链表的过程中,我们应当使用next
指针遍历整个链表,先将新链表的所有节点构造出来,然后再来逐个处理每一个节点的random
指针的指向问题。
还有一个问题,就是原链表中的节点A
的random
指针指向节点B
,我们怎么将新链表中A'
的random
指针指向B'
?
我们可以使用一个整形变量offset
来记录原链表中A -> random
指针指向节点(B
节点)相较于头节点的偏移量,然后我们在新链表中通过这个偏移量找到对应的节点,再将当前遍历到的节点的random
指针指向偏移量为offset
的节点。
下面结合一个简单的例子来说明一下解决的过程
代码如下
cpp
/*
// 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) {
Node* new_head = head ? new Node(head -> val) : nullptr; //新链表的头节点
Node* current1 = head;
Node* current2 = new_head;
//先根据next指针将所有节点构造出来,并顺序连接
while(current1){
current2 -> val = current1 -> val;
current2 -> next = current1 -> next ? new Node(current1 -> next -> val) : nullptr;
current1 = current1 -> next;
current2 = current2 -> next;
}
//按照顺序逐一构造random的指向
current1 = head;
current2 = new_head;
while(current1){
if(current1 -> random){ //random指向链表中的节点
Node* temp_current1 = head; //
int offset = 0; //计算偏移量
while(temp_current1 != current1 -> random){
++offset;
temp_current1 = temp_current1 -> next;
}
Node* temp_current2 = new_head;
while(offset > 0){ //寻找新链表中当前节点的random指向的位置
temp_current2 = temp_current2 -> next;
--offset;
}
current2 -> random = temp_current2;
}
current1 = current1 -> next;
current2 = current2 -> next;
}
return new_head;
}
};