输入:一个可能含有环的随机指针链表的头节点 head。
要求:深拷贝整个链表,并返回新链表的头节点。新链表中节点的 next 和 random 指针都必须指向新链表中的节点,而不是原链表中的节点。
输出:复制后新链表的头节点。
思路:三步法 (复制-链接-拆分)
-
复制与交织:遍历原始链表,对每个节点进行复制,并将新创建的复制节点插入到原节点的正后方。
- 初始链表:
A -> B -> C - 操作后变为:
A -> A' -> B -> B' -> C -> C' - 这样,对于任何一个旧节点
node,它的复制品node'就是node->next。
- 初始链表:
-
链接随机指针:再次遍历交织后的链表,处理原始节点。利用上一步建立的物理关联来设置新节点的
random指针。- 如果原始节点
A的random指向C,那么它的复制品A'的random就应该指向C的复制品C'。 - 根据第一步的结论,
A'就是A->next,而C'就是C->next。 - 因此,核心逻辑就是:
A->next->random = A->random->next。
- 如果原始节点
-
拆分链表:将交织的链表拆分成两个独立的链表:恢复原始链表,并构建出完整的复制链表。
- 遍历交织链表,将所有新节点(在奇数位置的节点)串联起来,同时恢复所有旧节点(在偶数位置的节点)的
next指针。
- 遍历交织链表,将所有新节点(在奇数位置的节点)串联起来,同时恢复所有旧节点(在偶数位置的节点)的
复杂度:
时间复杂度: O(n)
空间复杂度: O(1)
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
Node* dummy = new Node(-1, head, nullptr);
while (head) {
Node* tmp = new Node(head->val, head->next, nullptr);
head->next = tmp;
head = head->next->next;
}
head = dummy->next;
while (head) {
if (head->random != nullptr) {
head->next->random = head->random->next;
}
else {
head->next->random = nullptr;
}
head = head->next->next;
}
head = dummy->next;
Node* ans = new Node(-1, nullptr, nullptr);
Node* cur = ans;
while (head) {
cur->next = head->next;
head->next = head->next->next;
head = head->next;
cur = cur->next;
cur->next = nullptr;
}
return ans->next;
}
};
1655

被折叠的 条评论
为什么被折叠?



