剑指offer 复杂链表的复制
问题描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
C++代码实现
思路:1、暴力破解。先复制出主链表,然后复制从头复制random结点
2、map映射。
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if (!pHead)
{
return NULL;
}
// 要复制的结点
RandomListNode *phead1 = pHead;
// 创建复制后的首结点
RandomListNode *ph = (RandomListNode *)malloc(sizeof(RandomListNode));
// 声明指针指向复制后的首结点
RandomListNode *p1 = ph;
// 计算结点的个数
int num = 1;
// 复制完next链
while (phead1->next)
{
p1->label = phead1->label;
p1->next = (RandomListNode *)malloc(sizeof(RandomListNode));
phead1 = phead1->next;
p1 = p1->next;
num++;
}
p1->label = phead1->label;
p1->next = NULL;
// 改变新结点的random指针
phead1 = pHead;
p1 = ph;
while(phead1)
{
// 找到当前复制结点的random
RandomListNode *r = phead1->random;
// 判断random指向是倒数第几个结点
int n = 0;
while(r)
{
n++;
r = r->next;
}
// 新链表中找到指定结点
RandomListNode *p = ph;
for (int i = 0; i < num - n; i++)
{
p = p->next;
}
p1->random = p;
p1 = p1->next;
phead1 = phead1->next;
}
return ph;
}
};
python2代码实现
使用映射关系,将每个结点的random映射保存在字典中
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
p1 = pHead
nodes = []
d = {}
while p1:
nodes.append(p1)
p1 = p1.next
p1 = pHead
while p1:
if p1.random:
d[nodes.index(p1)] = nodes.index(p1.random)
else:
d[nodes.index(p1)] = -1
p1 = p1.next
new_nodes = [RandomListNode(x.label) for x in nodes]
for i, node in enumerate(new_nodes):
if i < len(new_nodes)-1:
node.next = new_nodes[i+1]
if d[i] != -1:
node.random = new_nodes[d[i]]
return new_nodes[0] if new_nodes else None