剑指 Offer 35. 复杂链表的复制 - 力扣(LeetCode) (leetcode-cn.com)
目录
方案1
首先把原链表节点逐个放入一个数组,然后把所有的random指针和它所指向的节点在数组中的下标关联起来。复制链表也需要一个指针数组,首先用指针数组把所有的节点都给开辟好,然后遍历一遍,根据原数组random指针指向的位置来调整好新链表random指针指向的节点.
运行结果
代码
class Solution {
#define scale 0x2BA
typedef Node* np; //node pointer
public:
Node* copyRandomList(Node* head) {
if (!head) return NULL;
unordered_map<np, int> nvgt; //navigation,导航
np* npList0 = new np[scale]; //node pointer list 0,原节点指针数组
int idx = 0;
for (np node_ptr = head; node_ptr; node_ptr = node_ptr->next) {
npList0[idx] = node_ptr;
nvgt[node_ptr] = idx; //把节点指针和该指针在数组中的位置关联起来,存入导航
++idx;
}
np* npList1 = new np[idx]; //node pointer list 1,新节点指针数组
npList1[0] = new Node(npList0[0]->val);
for (int i = 1; i != idx; ++i) { //首先初始化val和next指针
npList1[i] = new Node(npList0[i]->val);
npList1[i - 1]->next = npList1[i];
}
for (int i = 0; i != idx; ++i) {
npList1[i]->random = npList0[i]->random ? //最后根据原数组中random指针指向的位置调整新数组的random的指向
npList1[nvgt[npList0[i]->random]] : NULL;
}
return npList1[0];
}
};
方案2
用哈希表把原节点和对应的新节点一一关联起来。首先遍历一遍原链表,创建好新节点,然后建立新旧节点之间的对应,然后再次遍历原链表,就能直接根据哈希表设置好新节点的next和random两个指针。
运行结果
代码
class Solution {
public:
Node* copyRandomList(Node* head) {
unordered_map<Node*, Node*> nMp; //nMp: node map
for (Node* nptr = head; nptr; nptr = nptr->next) { //nptr: node pointer
nMp[nptr] = new Node(nptr->val);
}
for (Node* nptr = head; nptr; nptr = nptr->next) {
nMp[nptr]->next = nptr->next ? nMp[nptr->next] : NULL;
nMp[nptr]->random = nptr->random ? nMp[nptr->random] : NULL;
}
return nMp[head];
}
};
方案3(最佳解法)
遍历原链表,在每个原节点的后面插入新节点,这样就相当于直接建立起了新旧节点的对应关系,设置新节点的random指针的时候,直接根据原节点的random指针就能找到。最后把交织在一起的新旧链表拆开即可。
运行结果
代码
class Solution {
public:
Node* copyRandomList(Node* head) {
if (!head) return NULL;
//在每个原节点之后创建新节点
for (Node* nptr = head; nptr; nptr = nptr->next) { //nptr: node pointer
Node* nxt = nptr->next;
nptr->next = new Node(nptr->val);
nptr = nptr->next;
nptr->next = nxt;
}
//为新节点设置random指针
for (Node* orgn = head; orgn; orgn = orgn->next) { //orgn: original node
Node* newNode = orgn->next;
newNode->random = orgn->random ? orgn->random->next : NULL;
orgn = newNode;
}
Node* newHead = head->next;
Node* pre = new Node(NULL), * scapegoat = pre; //scapegoat: 替死鬼
//拆分新旧链表
for (Node* orgn = head; orgn; orgn = orgn->next) {
pre->next = orgn->next;
pre = pre->next;
orgn->next = pre->next;
}
delete scapegoat;
return newHead;
}
};