剑指35 复杂链表的复制
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
这题首先思路就比较复杂。
如果直接复制好基础链表,再复制random指针,就需要O(n^2)的时间,比较慢。
如果用哈希表记录下来每个节点的指针,可以化简到O(n),但是也需要O(n)的辅助空间。
最优方法为先复制每个节点,并插入在原节点后面;然后为每个复制节点建立random指针,这样random的目标直接就是原节点random的下一个节点;最后把复制的节点拆出来即可。
这里有两个点需要注意,一个是一定要留一个dummyhead指针指向链表头,否则会出现返回的是链表尾的情况;
第二个是在复制或者建立random指针时,原指针和copy指针会同步往后移动,要注意先移动原指针,因为最多也是移动为nullptr,同时在移动copy指针前要判断原指针是否已经为null,否则会出现访问null的情况。
1 /* 2 // Definition for a Node. 3 class Node { 4 public: 5 int val; 6 Node* next; 7 Node* random; 8 9 Node(int _val) { 10 val = _val; 11 next = NULL; 12 random = NULL; 13 } 14 }; 15 */ 16 class Solution { 17 public: 18 Node* copyRandomList(Node* head) { 19 if(head==nullptr) 20 return nullptr; 21 return copyeach(head); 22 } 23 24 Node* copyeach(Node* head){ 25 Node* cur=head; 26 while(cur!=nullptr){ 27 Node* copy=new Node(cur->val); 28 copy->next=cur->next; 29 cur->next=copy; 30 cur=copy->next; 31 } 32 return establish_random(head); 33 } 34 35 Node* establish_random(Node* head){ 36 Node* origin=head,*copied=head->next; 37 while(origin!=nullptr){ 38 if(origin->random!=nullptr){ 39 copied->random=origin->random->next; 40 } 41 origin=copied->next; 42 if(origin!=nullptr) 43 copied=origin->next; 44 } 45 /* 46 Node* temp=head; 47 while(temp!=nullptr){ 48 if(temp->random!=nullptr) 49 cout<<"val:"<<temp->val<<",random:"<<temp->random->val<<endl; 50 else 51 cout<<"val:"<<temp->val<<",null"<<endl; 52 temp=temp->next; 53 } 54 */ 55 return split(head); 56 } 57 58 Node* split(Node* head){ 59 Node* copied=head->next,*dummyhead=copied; 60 while(head!=nullptr){ 61 head->next=copied->next; 62 head=head->next; 63 if(head==nullptr) 64 break; 65 copied->next=head->next; 66 copied=copied->next; 67 } 68 return dummyhead; 69 } 70 };