【剑指offer】复杂链表的复制
原创文章,转载请注明出处!
1.题目
输入一个复杂链表,返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)。
- 复杂链表的数据结构
每个节点包含以下三个部分:节点值label,一个指向下一个节点next的指针,一个指向任意一个节点random的特殊指针。
struct RandomListNode { int label; struct RandomListNode *next; struct RandomListNode *random; }
- 复杂链表实例(含有5个节点的复杂链表)
2.思路
复杂链表的复制过程分成3个步骤,每个步骤的图形化方式如下:
- 新建复制节点的label和next、random
根据原链表上的每个节点N创建节点N’,然后把创建出来的节点用next连接起来
- 调整复制节点的random
- 拆分链表,其中奇数是原链表,偶数是复制的链表。
3.代码
复杂链表的复制分成三个步骤,每个步骤定义一个子函数。
class Solution { public: RandomListNode* Clone(RandomListNode* pHead) { // 第一步:复制原链表的节点,label和next CloneNodes(pHead); // 第二步:复制原链表的节点,random ConnectRandom(pHead); // 第三步:链表拆分,奇数是原链表,偶数是新链表 return ReconnectNodes(pHead); } // 第一步 void CloneNodes(RandomListNode* pHead) { // 遍历指针 RandomListNode* pNode = pHead; while(pNode!=nullptr) { // 创建节点(节点值) RandomListNode * pCloned = new RandomListNode(pNode->label); // 节点指针 pCloned->next = pNode->next; pCloned->random = pNode->random; // 节点连接 pNode->next = pCloned; // 节点移动 pNode = pCloned->next; } } // 第二步 void ConnectRandom(RandomListNode* pHead) { // 遍历节点 RandomListNode* pNode=pHead; RandomListNode* pCloned=nullptr; while(pNode!=nullptr) { // 建立连接 pCloned = pNode->next; if(pNode->random!=nullptr) { pCloned->random = pNode->random->next; } pNode = pCloned->next; } } // 第三步 RandomListNode* ReconnectNodes(RandomListNode* pHead) { // 遍历指针 RandomListNode* pNode = pHead; RandomListNode* pClonedHead = nullptr; RandomListNode* pClonedNode = nullptr; // 头结点 if(pNode!=nullptr) { pClonedHead = pClonedNode = pNode->next;// clone赋值 pNode->next = pClonedNode->next; // node断链 pNode = pNode->next; // node移位 }
// 循环移位 while(pNode!=nullptr) { pClonedNode->next = pNode->next; // clone断链 pClonedNode = pClonedNode->next; // clone移位 pNode->next = pClonedNode->next; // node断链 pNode = pNode->next; // node移位 } return pClonedHead; } };