题目:剑指 Offer 35. 复杂链表的复制

方法一。
对于每个新节点,遍历新链表来寻找对应的random节点,时间复杂度是O(n^2)。
方法二
由于方法一的时间主要花费再定位random节点上,可以在这方面着手去优化。可以讲解题分为两步,第一步仍然是复制原链表生成新链表,并将节点配对信息存储在哈希表中。这样就能以O(1)的时间找到random节点。同时也相当于是用空间换时间,因为我们需要一个O(n)大小的哈希表。
方法三(参考剑指offer解析)
将解题步骤分为三步,第一步仍然是复制原链表,但不同的是,将复制出来的节点链接在原节点之后,串成一个链表。
void cloneNodes(Node* head){
Node* cur = head;
while(cur){
Node* newNode = new Node(0);
newNode->val = cur->val;
newNode->next = cur->next;
cur->next = newNode;
cur = newNode->next;
}
}
第二步则是给新节点赋值random节点,由于整个链表是串行的,所以整体只需要O(N) 的时间。
void connectRandomNodes(Node* head){
Node* cur = head;
while(cur){
if(cur->random){
cur->next->random = cur->random->next;
}
cur = cur->next->next;
}
}
第三步则是将链表分离为原链表和新链表。
Node* reconnectNodes(Node* head){
Node* cur = head;
Node* cloneHead = NULL;
Node* cloneCur = NULL;
if(cur != NULL){
cloneHead = cur->next;
cloneCur = cur->next;
cur->next = cloneCur->next;
cur = cur->next;
}
while(cur){
cloneCur->next = cur->next;
cloneCur = cur->next;
cur->next = cloneCur->next;
cur = cur->next;
}
return cloneHead;
}
最后将这三步串联起来形成题解。
Node* copyRandomList(Node* head) {
//首先复制链表中每个节点,并链接在每个原结点后
cloneNodes(head);
//再讲所有复制节点的random指针指向对应node
connectRandomNodes(head);
//最后再分割链表为两个
return reconnectNodes(head);
}
坑点
方法三的第三步里,因为循环的条件是原链表的cur指针是否为空,所以巧妙的使原链表的cur指针走在新链表cur指针的前面,可以减少对于边界情况null指针的判断。这样不仅简洁也增强了代码的鲁棒性。