剑指offer 35题 复制复杂链表
把原题用我们能理解的白花来翻译一下:
复制出一个跟原链表一摸一样的链表,原链表每个节点的值是多少,你复制出来的链表的值就是多少,原链表每个节点的random指向哪,你复制出来的链表的节点的random也要指向对应的位置。
原链表:
说一下思路:3个步骤
步骤1:复制节点
我们步骤一要实现出来的就是上图所示。这个步骤可以理解为链表的插入,需要插入的节点我们在循环里面创建
for( auto p = head; p; )
{
auto newp = new Node(p->val);//复制出当前节点
auto temp = p->next;//定义一个指针一直指向p的下一个
p->next = newp;//这块改变的p的下一个指向,所以前面要预先定义以一个指针指向p->next
newp->next = temp;
p = temp; //这三步就是链表节点的插入
}
步骤2:复制random
这块我们暂且定义p=head,p是我们链表的头
上图是我们本步骤的一个思路,为了怕大家不理解代码,我在图中进行了标注。需要注意,我们本步骤2是在步骤1的基础之上进行操作,也就是说此时链表已经完成了复制,此时p->next是我们已经复制出来的一个节点。通过上图我们可以发现1 1‘ 2 2’ 的一个关系:1----2 1‘-----2’ ,然而2的下一个就是2‘,即2->next = 2’ ,2是1的random,1又是头,所以有p->random->next = 2' ,2'是1‘的random,1’又是头的下一个,所以有2’ = p->next->random。
故p->random->next = p->next->random;
for( p = head; p; p = p->next->next )
{
if( p->random )
{
p->next->random = p->random->next;
}
}
步骤3:分离
上图是我们要得到的结果,什么意思呢,就是从1 1‘ 2 2’ 3 3‘ 4 4’ 中分离出 1‘ 2’ 3‘ 4’
p = head(也就是1)。p->next是1‘,就是我们要分离出来的
auto dummy = new Node(-1); //建立一个虚拟节点
auto cur = dummy; //随便定义一个指针指向该虚拟节点,不定义也没事
for( auto p = head; p; p=p->next )
{
cur->next = p->next; //虚拟节点的下一个指向头节点的下一个,也就是1’
cur = cur->next; //虚拟节点后移
p->next = p->next->next; //头指针后移 此时p要一次移动2步,
}
return dummy->next; //此时我们返回虚拟节点的下一个 1‘即可。
附上力抠代码原图: