题目描述
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
思考
本题在传统链表节点的结构体内加入了一个random指针,这个指针可以指向链表中的任意节点或者指向NULL,我们需要做的事情是返回该链表的一个深度拷贝。
关于赋值、浅拷贝、深拷贝不是很清楚的话可以阅读博文《深入C++的拷贝构造和赋值函数》以及《C++类的赋值运算符“=”重载以及深拷贝和浅拷贝》。
我拿到本题的第一想法是,直接暴力实现......但是这种题一般都会有一个较优的解法,想了一会没有想出来,就直接使用暴力解法了。
暴力解法就是我们首先创建一个新的链表newH,该链表中各个节点的label以及next是与原链表head对应的,只不过该链表中所有的random指针为NULL。然后我们遍历原链表,并且使用一个tempP指针来寻找原链表中random指针指向的节点,移动tempP的同时移动一个指向新链表的指针tempQ,将tempQ赋给新链表中对应节点的random指针。等到遍历对原始链表遍历完成,那么任务也就完成了。
给出代码如下:
/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head == NULL){
return NULL;
}
RandomListNode* p = head;
RandomListNode* newH = new RandomListNode(0);
RandomListNode* q = newH;
while(p != NULL){
q->next = new RandomListNode(p->label);
p = p->next;
q = q->next;
}
p = head;
q = newH->next;
while(p != NULL){
RandomListNode* tempP = head;
RandomListNode* tempQ = newH->next;
while(tempP != p->random && p->random != NULL){
tempP = tempP->next;
tempQ = tempQ->next;
}
if(p->random == NULL){
q->random == NULL;
}
else{
q->random = tempQ;
}
q = q->next;
p = p->next;
}
return newH->next;
}
};
关于这种暴力解法我们就不赘述了,下面我们来看看讨论区的大佬们的解法。大佬们为了避免上面代码中的双重while循环,而想到了一个很有趣的idea,就是我们在对新链表的节点进行定义之后,插入到原链表对应的节点后面,然后赋值random指针,最后再把新链表从原链表中抽出。
代码如下:
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head == NULL){
return NULL;
}
RandomListNode* p = head;
while(p != NULL){
RandomListNode* temp = new RandomListNode(p->label);
temp->next = p->next;
p->next = temp;
p = p->next->next;
}
p = head;
while(p != NULL){
if(p->random != NULL){
p->next->random = p->random->next;
}
p = p->next->next;
}
RandomListNode* newH = new RandomListNode(0);
p = head;
RandomListNode* q = newH;
while(p != NULL){
q->next = p->next;
p->next = q->next->next;
q->next->next = NULL;
p = p->next;
q = q->next;
}
return newH->next;
}
};
暴力解法的运行时间是86ms,运行内存是1900K,而上面这种解法的运行时间是18ms,运行内存是1200K。
好了,本题的介绍就到这里,大家周末愉快~