一、题目描述:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
二、思路分析:
以以下链表为例:
- 第一步:复制复杂链表节点的label和next。把复制的结点插在原结点后面,而不是直接创建新的链表;
- 第二步:设置复制出来的新结点的random指针。因为新旧结点是前后对应关系,所以根据原节点的random指针也是一步就能找到新节点的random;
- 第三步:拆分链表。pClonedHead为新链表的头结点。指针pNode通过遍历得到原链表,指针pClonedNode通过遍历得到新链表
pNode->next = pClonedNode->next; //建立原节点的链接关系
pNode = pNode->next;//更新pNode,遍历原节点
pClonedNode->next = pNode->next;//建立新节点的链接关系
pClonedNode = pClonedNode->next;//更新pClonedNode,遍历新节点
C++:
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
//第一步,复制复杂链表的节点(值label和next指针),并插入到原链表中
void CloneNodes(RandomListNode* pHead){
RandomListNode* removeNode = pHead;//指针,用于遍历原链表
while(removeNode != NULL){
RandomListNode* pCloned = new RandomListNode(-1);//创建一个新节点
pCloned->label = removeNode->label;//复制节点值
pCloned->next = removeNode->next;//复制节点next指针的链接关系
removeNode->next = pCloned;//将新节点插入到原链表中
removeNode = pCloned->next;//更新指针
}
}
//第二步,构建新节点的random指针的链接关系
void Connect_random(RandomListNode* pHead){
RandomListNode* removeNode = pHead;//指针,遍历原链表
while(removeNode != NULL){//遍历原链表,给新的节点的random指针建立链接关系
RandomListNode* pCloned = removeNode->next;//指针,指向新节点
if(removeNode->random != NULL){//如果原节点的random指针不为空,则复制的新节点的random指针不为空
pCloned->random = removeNode->random->next;//因为复制的新节点总是插在原节点的后面
}
removeNode = pCloned->next;//更新遍历指针
}
}
//第三步:拆分得到复制后的新的复杂链表,奇数节点为原链表,偶数节点为新链表
RandomListNode* ReconnectNodes(RandomListNode* pHead){
RandomListNode* pNode = pHead;//指针,每次更新该指针,使其遍历原节点
RandomListNode* pClonedHead = NULL;//初始化为空,后面赋值使其指向复制后新链表的head,最后返回
RandomListNode* pClonedNode = NULL;//指针,每次更新该指针,使其遍历复制后的新节点
if(pNode != NULL){
pClonedHead = pClonedNode = pNode->next;//让两个指针都指向复制的第一个节点1‘
pNode->next = pClonedNode->next;//让节点1指向原节点2
pNode = pNode->next;//pNode->next是原节点2,所以这里是更新指针pNode,由原节点1更新为指向原节点2
}
while(pNode != NULL){
pClonedNode->next = pNode->next;//让新节点1’指向新节点2‘,...
pClonedNode = pClonedNode->next;//更新pClonedNode指针,指向2'
pNode->next = pClonedNode->next;//让原节点2指向原节点3
pNode = pNode->next;//更新指针pNode,指向原节点3,
}
return pClonedHead;
}
RandomListNode* Clone(RandomListNode* pHead)
{//假设原复杂链表为:1->2->3(1同时指向3)
//思路: 1->1'->2->2'->3->3'(1同时指向3,1‘指向3’)
//经过以下三步可得到复制后的复杂链表,每个步骤用单独的一个函数实现
CloneNodes(pHead);
Connect_random(pHead);
return ReconnectNodes(pHead);
}
};