剑指Offer-25.复杂链表的复制(C++/Java)
题目:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
分析:
拷贝一个带有random指针的链表。
首先想到的便是,复制原链表的的每一个节点,并用next连接起来,在遍历原链表的时候,将原节点和新复制的节点的映射存进map中<Node,Node'>。然后再同时遍历原链表和新链表,此时新链表的random指针指向的元素便是原链表节点指向的节点在map中的映射,也就是A(random)->B,那么A'(random)->(map[A(random)]),因为在map中存储了原节点和新节点的对应关系,可以在O(1)的时间查找到。
还有一种方法是先遍历原链表,将复制的节点插在原链表节点的后面,也就是A->A'->B->B'->NULL,这样的话,复制的节点和原节点也就有了对应的关系,新复制的节点random指向的元素便是原节点random指向的元素的下一个元素,所有新节点random处理完毕后将这个链表再拆分成两个链表即可。
第一步:复制节点,将新创建的节点N'接到N的后面。
第二步:复制random指针
第三步:拆分链表
程序:
C++
//use hashmap class Solution { public: RandomListNode* Clone(RandomListNode* pHead) { RandomListNode* myHead = new RandomListNode(-1); RandomListNode* p = pHead; RandomListNode* q = myHead; while(p != nullptr){ RandomListNode* tempNode = new RandomListNode(p->label); m[p] = tempNode; q->next = tempNode; p = p->next; q = tempNode; } p = pHead; q = myHead->next; while(p != nullptr){ if(p->random != nullptr) q->random = m[p->random]; p = p->next; q = q->next; } return myHead->next; } private: map<RandomListNode*, RandomListNode*> m; };
class Solution { public: RandomListNode* Clone(RandomListNode* pHead) { if(pHead == nullptr) return nullptr; RandomListNode* p = pHead; //在每个节点A后复制一个相同的节点A',A->B->C->NULL, A->A'->B->B'->C->C'->NULL while(p != nullptr){ RandomListNode* tempNode = new RandomListNode(p->label); tempNode->next = p->next; p->next = tempNode; p = tempNode->next; } //复制random指针,A'random指向的一定是Arandom指向的下一个元素。 p = pHead; while(p != nullptr){ if(p->random != nullptr) p->next->random = p->random->next; p = p->next->next; } //将链表拆分,A->A'->B->B'->C->C'->NULL,A->B->C->NULL and A'->B'->C'->NULL p = pHead; RandomListNode* myHead = pHead->next; RandomListNode* q = myHead; while(p != nullptr){ p->next = q->next; //如果处理到最后一组节点时,q不用再做处理,因为其next已经指向nullptr if(q->next != nullptr) q->next = p->next->next; p = p->next; q = q->next; } return myHead; } };
Java
import java.util.HashMap; public class Solution { public RandomListNode Clone(RandomListNode pHead) { RandomListNode myHead = new RandomListNode(-1); RandomListNode p = pHead; RandomListNode q = myHead; while(p != null){ RandomListNode tempNode = new RandomListNode(p.label); q.next = tempNode; map.put(p, tempNode); p = p.next; q = q.next; } p = pHead; q = myHead.next; while(p != null){ if(p.random != null) q.random = map.get(p.random); p = p.next; q = q.next; } return myHead.next; } private HashMap<RandomListNode, RandomListNode> map = new HashMap<>(); }