难度 中等 题目链接
1. 方法一
示例:
解题思路:
首先,大家肯定会这样想:定义一个cur循环遍历,每次遍历一个,就malloc一个。
当遍历后面的时候,就开始尾插。
但现在有一个问题是:这个random指针该这么拷贝呢?因为我们不知道我们拷贝的random该去指向那个结点的地址。有的同学会说找val值,这是不行的。因为可能会有相同的值,你不知道该指向哪一个。
解决方法:
1. 拷贝结点连接在原结点后面。
2. 连接拷贝结点的random,拷贝结点的random在原结点random指向结点的next。
那么第一个7的random很简单是NULL,我们直接指向NULL就行了,无需去找。
第二个13的random是原结点13的random指向的结点7的next
后面的结点的random也是按照这样的方式来找,然后连接起来。
3. 把拷贝结点解下来,连接到一起。
代码实现步骤:
我们用一个cur来遍历,然后把拷贝结点的叫做copy。
现在我们要把拷贝结点连接在原结点的后面,但我们不能这样去连接:
因为这样去连接,我们就找不到13结点的地址了。所以我们只能这样去连接。
下一步就是找下一个结点,可以是cur的next的next或者是copy的next
那么后面的结点也是按照这样的方式来。拷贝结点完成了之后,我们就需要找到拷贝结点的random。
我们这里还是用cur和copy来遍历。如果原结点的random指向的是NULL,我们拷贝结点的random直接指向NULL。
如果原结点random不指向NULL,那么拷贝结点的random就为原结点的random的next
然后我们在找下一个原结点。
这样第二步也完成了,所以拷贝结点的random都连接好了。现在我们要开始第三步,把所有的拷贝结点解下来,然后连接在一起。连接在一起也就是尾插。
我们这里使用三个指针cur,copy,next,这样的话会好控制一点。
因为是尾插,我们可以先定义一个copyHead和copyTail,把这两个先置为NULL。如果为NULL,就直接赋值。如果不为空,就将copy尾插。
我们尾插之前也可以把原链表还原一下。还原的话就是把cur->next=next
此时,拷贝结点就是这个样子了:
那么我们就需要更新cur,让它找到下一个原结点。下一个原结点的地址就是next,直接赋值给cur就行了。copy和next也继续更新。
此时我们就需要尾插了。我们把copy结点插在copyTail的next上,然后更新一下copyTail。
最后return拷贝链表的头指针copyHead。
完整代码如下:
2. 方法二
用map来记录老结点和新结点。
遍历一遍老链表,在map的value中拷贝新结点:
再遍历一遍老链表,在map中找到新结点(value),它的next就是map中老结点的next。它的random就是map中老结点的random。
完整代码: