A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
/** * Definition for singly-linked list with a random pointer. * struct RandomListNode { * int label; * RandomListNode *next, *random; * RandomListNode(int x) : label(x), next(NULL), random(NULL) {} * }; */
我的解题思路如下:
- 第一次遍历原始链表做两件事:
1.1 将每一个节点的地址(key)和在链表中的位置(value)组成的key-value插入map,这样之后通过查找random对应的value就可以知道random所指向的节点的位置(下标从0索引);
1.2 新建并复制每一个节点的label,next和random指针均为NULL,将新建节点的地址依次插入vector,这样之后就可以通过random所指向的节点的位置获取节点的地址。 - 第二次遍历原始链表也做两件事:
2.1 将新建节点通过next指针串联起来成为复制链表;
2.2 对于每一个原始节点:在map中查找该节点的random所指向的节点的位置,通过该位置在vector中得到新建链表中对应节点的地址,将该地址赋给复制节点的random即可。
代码实现如下:
RandomListNode *copyRandomList(RandomListNode *head) {
if (!head) return head;
map<RandomListNode *, int> positions;
vector<RandomListNode *> cpyList;
int pos = 0;
for (RandomListNode *curr = head; curr != NULL; curr = curr->next, ++pos) {
positions.insert(pair<RandomListNode *, int> (curr, pos));
RandomListNode *newNode = new RandomListNode(curr->label);
cpyList.push_back(newNode);
}
cpyList.push_back(NULL);
pos = 0;
for (RandomListNode *curr = head; curr != NULL; curr = curr->next, ++pos) {
cpyList[pos]->next = cpyList[pos + 1];
cpyList[pos]->random = curr->random ? cpyList[positions[curr->random]] : NULL;
}
return cpyList[0];
}
上面代码的时间复杂度是O(N),空间复杂度是O(N)。
在Discuss上寻求更好的解法,看到一个空间复杂度为O(1)的解法,构思非常巧妙:
- 每一个原始链表的节点后面新建一个拷贝节点,e.g.
1->2->3
变为1->1->2->2->3->3
。此时拷贝节点的random均为NULL。 - 将拷贝节点的random指向正确的位置。
- 将链表拆开成为两条链表,返回拷贝链表。
具体代码实现如下:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head == NULL) return NULL;
RandomListNode *p = head;
while(p != NULL) {
RandomListNode *q = p->next;
p->next = new RandomListNode(p->label);
p->next->next = q;
p = q;
}
for (p = head; p != NULL; p = p->next->next)
p->next->random = (p->random == NULL) ? NULL : p->random->next;
p = head;
RandomListNode *r = head->next;
for(RandomListNode *q = r;;) {
p->next = q->next;
p = p->next;
if(p == NULL) break;
q->next = p->next;
q = q->next;
}
return r;
}