/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
复制链表并拆分 思路: 直接在原链表基础上复制新链表,即让原节点next指向自己的拷贝节点,然后拆分random, 拷贝节点的random指向其指向的原节点的next,最后,再拆next,让其每一个节点next都指向其原来指向的下一节点, 文字描述有点晦涩,直接上图(图中合并部分,即拷贝过程中,由于空间有限,没有画出原有链表的random指向, 其实原有链表的指向和拷贝之前的一样) Step1:复制原链表中每一个节点,使得拷贝后的新节点在原节点的下一个节点; Step2:拷贝后的新节点的random指向节点与原链表节点的random指向节点一致; Step3:拆分链表,原节点依次连接,拷贝后的新节点依次连接。 * 哈希表 使用哈希表map表示映射关系,其中哈希表的键值key是原节点,value值是复制的新节点。 步骤: 第一步是遍历原链表,利用哈希表映射新节点和旧节点关系,即每遍历一个节点,则复制一个val值相同的新节点, mp[p]= new Node(p->val)。 第二步是遍历map,复制next和random指针的对应关系,并更新新节点的next和random所指的值, 最后返回新链表的头节点即可,即即mp[p]->next=mp[p->next]和mp[p]->random=mp[p->random]。
class Solution { public: /* 复制链表并拆分 思路: 直接在原链表基础上复制新链表,即让原节点next指向自己的拷贝节点,然后拆分random, 拷贝节点的random指向其指向的原节点的next,最后,再拆next,让其每一个节点next都指向其原来指向的下一节点, 文字描述有点晦涩,直接上图(图中合并部分,即拷贝过程中,由于空间有限,没有画出原有链表的random指向, 其实原有链表的指向和拷贝之前的一样) Step1:复制原链表中每一个节点,使得拷贝后的新节点在原节点的下一个节点; Step2:拷贝后的新节点的random指向节点与原链表节点的random指向节点一致; Step3:拆分链表,原节点依次连接,拷贝后的新节点依次连接。 */ /* RandomListNode* Clone(RandomListNode* pHead) { if(pHead == nullptr) { return nullptr; } //Step1:复制原链表中每一个节点,使得拷贝后的新节点在原节点的下一个节点; RandomListNode *pHeadNode = pHead; while(pHeadNode != nullptr) { RandomListNode *pNewNode = new RandomListNode(pHeadNode->label); //创建头结点 RandomListNode *pNextNode = pHeadNode->next; //下一个节点 pHeadNode->next = pNewNode; //尾插法:头结点连接新节点 pNewNode->next = pNextNode; //新节点连接下一个节点 pHeadNode = pNewNode->next; //向后移位 } // Step2:拷贝后的新节点的random指向节点与原链表节点的random指向节点一致; pHeadNode = pHead; while(pHeadNode != nullptr) { if (pHeadNode->random != nullptr) { pHeadNode->next->random = pHeadNode->random->next; } pHeadNode = pHeadNode->next->next; } // Step3:拆分链表,原节点依次连接,拷贝后的新节点依次连接。 pHeadNode = pHead; RandomListNode *pFirstNode = pHead->next; RandomListNode *pSecondNode = pHead->next; while(pHeadNode != nullptr) { pHeadNode->next = pHeadNode->next->next; //第一个节点连接第三节点,断开第二个节点 pHeadNode = pHeadNode->next; //向后移位 if(pFirstNode->next != nullptr) { pFirstNode->next = pFirstNode->next->next; pFirstNode = pFirstNode->next; } } return pSecondNode; } */ /* * 哈希表 使用哈希表map表示映射关系,其中哈希表的键值key是原节点,value值是复制的新节点。 步骤: 第一步是遍历原链表,利用哈希表映射新节点和旧节点关系,即每遍历一个节点,则复制一个val值相同的新节点, mp[p]= new Node(p->val)。 第二步是遍历map,复制next和random指针的对应关系,并更新新节点的next和random所指的值, 最后返回新链表的头节点即可,即即mp[p]->next=mp[p->next]和mp[p]->random=mp[p->random]。 */ RandomListNode* Clone(RandomListNode* pHead) { if(pHead == nullptr) { return nullptr; } unordered_map<RandomListNode*, RandomListNode*> mpNode; RandomListNode* pHeadNode = pHead; while(pHeadNode != nullptr) { mpNode[pHeadNode] = new RandomListNode(pHeadNode->label); pHeadNode = pHeadNode->next; } pHeadNode = pHead; while(pHeadNode != nullptr) { if(pHeadNode->next != nullptr) { mpNode[pHeadNode]->next = mpNode[pHeadNode->next]; // 拷贝节点连接下一个节点 } if(pHeadNode->random != nullptr) { mpNode[pHeadNode]->random = mpNode[pHeadNode->random]; } pHeadNode = pHeadNode->next; } return mpNode[pHead]; } };