剑指offer系列19:复杂链表的复制
这道题是典型的分治法,将一个大问题分解成几小步解决。一定要注意在使用指针的时候指针指向是否为空的问题。在指针指向时,可以将一个指向为空的指针作为赋值来写,但是空指针不能指向任何地方(指向空也不行),这点一定要记住。
#include<iostream> #include<vector> using namespace std; struct RandomListNode { int label; struct RandomListNode *next, *random; /* RandomListNode(int x) : label(x), next(NULL), random(NULL) { } */ }; class Solution { public: RandomListNode* Clone(RandomListNode* pHead) { if (pHead == NULL) return NULL; //3步 //第一步,将复杂链表复制成double nodeclone(pHead); connect(pHead); return reconnect(pHead); } void nodeclone(RandomListNode* Head) { RandomListNode*p = Head; while (p != NULL) { //插入节点 //cur = p->next; RandomListNode *curnode = new RandomListNode(); curnode->label = p->label; curnode->next = p->next; curnode->random = NULL;//这一句必须要写? p->next = curnode; p = curnode->next;//悬浮指针? } } void connect(RandomListNode* Head) { //第二步:将复制出的结点的随机指针指向该有的位置 RandomListNode*p = Head; while (p != NULL)//在指针访问的时候,时刻注意是否为空 { RandomListNode *curnode = p->next; if (p->random != NULL) { curnode->random = p->random->next; } p = curnode->next; } } RandomListNode *reconnect(RandomListNode* Head) { //第三步:将链表拆为两部分 RandomListNode*p = Head; RandomListNode *copy = p->next; while (p!= NULL) { RandomListNode *curnode = p->next; if (curnode != NULL) { p->next = curnode->next; } p = curnode; } return copy; } }; int main() { RandomListNode list[5]; list[0].label = 1; list[0].next = &list[1]; list[0].random = &list[2]; list[1].label = 2; list[1].next = &list[2]; list[1].random = &list[4]; list[2].label = 3; list[2].next = &list[3]; list[2].random = NULL; list[3].label = 4; list[3].next = &list[4]; list[3].random = &list[1]; list[4].label = 5; list[4].next =NULL; list[4].random = NULL; Solution solu; RandomListNode *re = solu.Clone(list); int count=0; while (re != NULL) { //cout << re->label << " "<<re->random->label<<","; cout << re->label<<" "; if (re->random != NULL) cout << re->random->label; cout << endl; count++; re = re->next; } //cout << endl; cout << "number of array:"<<count << endl; return 0; }
解法2:
如果是一个普通链表,直接可以循环去复制链表。但是复杂链表的问题在于有一个random结点,如果循环的时候给random赋值,random的指向不明确,有可能这个结点还没出现,因为链表不能随机访问。所以难点在于如何去赋值这个随机的random结点。
想到这里,可以利用hash表来解答此题,将原来的节点和拷贝后的节点作为(key,value)存在dict里,第一遍先复制链表中的值和关系,然后再遍历一次去赋值random结点。代码如下:
1 def Clone(self, head): 2 if head is None: 3 return head 4 # 复制后的链表的头结点 5 res = RandomListNode(0) 6 # 建立一个字典,(key,value)是复制前和复制后的节点 7 mp = dict() 8 cur = head 9 pre = res 10 # 复制链表中的lable和next 11 while cur: 12 # 复制lable 13 clone = RandomListNode(cur.label) 14 # 放入hash表中 15 mp[cur] = clone 16 # 复制连接关系 17 pre.next = clone 18 # 循环条件 19 pre = pre.next 20 cur = cur.next 21 # 复制链表中的random 22 for (key, value) in mp.items(): 23 if key.random is None: 24 value.random = None 25 else: 26 value.random = mp[key.random] 27 return res.next

浙公网安备 33010602011771号