复杂链表的复制(剑指Offer-35)

题面

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

示例

示例 1:

1输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
2输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例 2:

1输入:head = [[1,1],[2,1]]
2输出:[[1,1],[2,1]]

示例 3:

1输入:head = [[3,null],[3,0],[3,null]]
2输出:[[3,null],[3,0],[3,null]]

示例 4:

1输入:head = []
2输出:[]
3解释:给定的链表为空(空指针),因此返回 null。

限制

1    -10000 <= Node.val <= 10000
2    Node.random 为空(null)或指向链表中的节点。
3    节点数目不超过 1000 。

思路

  • 复制各节点,构建拼接链表: 设原链表为 node1 → node2 → ⋯,构建的拼接链表如下所示: node1 → node1new → node2 → node2new → ⋯

  • 构建新链表各节点的 random 指向: 当访问原节点 cur 的随机指向节点 cur.random 时,对应新节点 cur.next 的随机指向节点为 cur.random.next 。

  • 拆分原 / 新链表: 设置 pre / cur 分别指向原 / 新链表头节点,遍历执行 pre.next = pre.next.next 和 cur.next = cur.next.next 将两链表拆分开。

  • 返回新链表的头节点 res 即可。

代码

 1/*
 2// Definition for a Node.
 3class Node {
 4public:
 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*/
16class Solution {
17public:
18    Node* copyRandomList(Node* head) {
19        if(head == nullptr) return nullptr;
20        Node *cur = head;
21
22        while(cur != nullptr){
23            Node *t = new Node(cur->val);
24            t->next = cur->next;
25            cur->next = t;
26            cur = t->next;
27        }
28
29        cur = head;
30        while(cur != nullptr){
31            if(cur->random != nullptr)
32                cur->next->random = cur->random->next;
33            cur = cur->next->next;
34        }
35
36        cur = head->next;
37        Node *pre = head, *res = head->next;
38        while(cur->next != nullptr){
39            pre->next = pre->next->next;
40            cur->next = cur->next->next;
41            pre = pre->next;
42            cur = cur->next;
43        }
44        pre->next = nullptr;
45        return res;
46    }
47};