题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
解题思路
最简单的是使用暴力解法。
本题的数据结构:节点有三个部分组成:label域存数值,next域存该节点的下一个节点地址,random域存该节点随便指向的一个节点地址。
暴力解法分为两步实现:1.首先复制next域:只用遍历一次原链表。(常规链表的遍历)
2.复制 random域:对每个节点来说,都要遍历链表。
命题变为:已知原链表中的当前节点和当前节点的random域,希望能够找到复制链表的相应节点的random域。因此同时遍历原链表和复制链表。当原链表的节点为当前节点的random指针指向的节点时,复制链表的遍历指针也指向了复制链表相应节点的random域。
对每一个链表重复上述操作即可。
代码实现
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public://首先使用暴力解法。
//分为两步进行:第一次复制next域,此时只用遍历一次pHead所指向的连表就可以了。
//第二次复制random域。对于某一个节点来说,首先在pHead中找到该节点的random所指的节点randNode。
//之后和newHead一起从头开始遍历,当pHead遍历到randNode节点的时候,newHead也遍历到了复制节点对应的random域。
RandomListNode* FindListNode(RandomListNode* oldHead,RandomListNode* newHead,RandomListNode* randomNode){
RandomListNode* currNode=oldHead;
RandomListNode* newNode=newHead;
while(currNode&&newNode){//当这两个节点指针都不指向空
if(currNode==randomNode){//当原链表的指针指向randomNode的时候,
return newNode;
}
currNode=currNode->next;
newNode=newNode->next;
}
return nullptr;
}
RandomListNode* Clone(RandomListNode* pHead)
{
RandomListNode* currNode=pHead;
RandomListNode* newHead=nullptr,*newNode=nullptr,*preNode=nullptr;
while(currNode){//复制next域,普通链表的复制
newNode=new RandomListNode(currNode->label);
currNode=currNode->next;
if(preNode==nullptr){//如果preNode是空指针,说明newHead还未指向任何节点
newHead=newNode;
}else{
preNode->next=newNode;
}
preNode=newNode;
}
//复制random域
currNode=pHead;
newNode=newHead;
while(currNode){
RandomListNode* rand=currNode->random;
RandomListNode* newRand=FindListNode(pHead,newHead,rand);
newNode->random=newRand;
newNode=newNode->next;
currNode=currNode->next;
}
return newHead;
}
};
代码测试
以下做五个测试,分别是:
1.空链表测试
2.普通复杂链表测试
3.节点random域指向自身的链表的测试
4.只有一个节点的测试
5.存在两个护指节点的链表的测试
代码如下:
int main()
{
//Test1:空链表
RandomListNode* node = nullptr;
//Test2:普通随机链表
RandomListNode* node0 = new RandomListNode(0);
RandomListNode* node1 = new RandomListNode(1);
RandomListNode* node2 = new RandomListNode(2);
RandomListNode* node3 = new RandomListNode(3);
RandomListNode* node4 = new RandomListNode(4);
node0->next = node1;
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = nullptr;
node0->random = node2;
node1->random = node4;
node3->random = node1;
//Test3:random域指向自身
RandomListNode* node5 = new RandomListNode(5);
RandomListNode* node6 = new RandomListNode(6);
node5->next = node6;
node6->next = nullptr;
node5->random = node5;
//Test4:只有一个节点的链表
RandomListNode* node7 = new RandomListNode(7);
node7->next = nullptr;
node7->random = node7;
//Test5:两个链表节点互相指,从而形成环状
RandomListNode* node8 = new RandomListNode(8);
RandomListNode* node9 = new RandomListNode(9);
RandomListNode* node10 = new RandomListNode(10);
RandomListNode* node11 = new RandomListNode(11);
RandomListNode* node12= new RandomListNode(12);
node8->next = node9;
node9->next = node10;
node10->next = node11;
node11->next = node12;
node12->next = nullptr;
node9->random = node11;
node11->random = node9;
//判断是否是值相同的链表:先打印链表,再打印每个节点的random域。
cout << "******************Test1:空链表测试******************" << endl;
RandomListNode* ans = Clone(node);
cout << "原链表:" << endl;
print(node);
cout << endl;
cout << "复制链表:" << endl;
print(ans);
cout << "******************Test2:空链表测试******************" << endl;
RandomListNode* ans0 = Clone(node0);
cout << "原链表:" << endl;
print(node0);
cout << endl;
cout << "复制链表:" << endl;
print(ans0);
cout << "******************Test3:random域指向自身链表测试******************" << endl;
RandomListNode* ans1 = Clone(node5);
cout << "原链表:" << endl;
print(node5);
cout << endl;
cout << "复制链表:" << endl;
print(ans1);
cout << "******************Test4:只有一个节点的链表测试******************" << endl;
RandomListNode* ans2 = Clone(node7);
cout << "原链表:" << endl;
print(node7);
cout << endl;
cout << "复制链表:" << endl;
print(ans2);
cout << "******************Test5:存在两个节点护指的链表测试******************" << endl;
RandomListNode* ans3 = Clone(node8);
cout << "原链表:" << endl;
print(node8);
cout << endl;
cout << "复制链表:" << endl;
print(ans3);
return 0;
}
测试结果如下所示:
测试全都通过。