复杂链表的复制
复杂链表的复制
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针:一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的 head。
注意:输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空。
解题思路
初次审题看似简单,实质是复制链表,但在实际操作中容易出现各种 Bug,例如提交后提示返回空指针。这通常是因为未严格遵守“不返回参数中的节点引用”这一要求,即需要重新创建一个链表,并将原链表节点逐个复制过来。
目前主要有两种实现思路:
- 递归法
每一次递归复制一个节点。该思路简洁且代码量少。使用 JavaScript 实现该思路可通过评测,但 Java 实现可能因评测系统差异或栈深度限制遇到问题。 迭代法(交错复制)
另一种思路是通过三次遍历完成复制,具体步骤如下(图解参考自网络):- 复制节点:将每一个复制的节点放在原节点后面。
- 复制随机节点:利用交错关系设置随机指针。
- 拆分链表:将复制的链表和原来的链表分开。
在代码实现过程中,逻辑细节较难把握,但结合上述图解会更易理解。
- 复制节点:将每一个复制的节点放在原节点后面。
代码实现
JavaScript 版本(递归思路)
/*function RandomListNode(x){
this.label = x;
this.next = null;
this.random = null;
}*/
function Clone(pHead) {
if (pHead == null)
return pHead;
var a = new RandomListNode(pHead.label);
a.random = pHead.random;
a.next = Clone(pHead.next);
return a;
// write code here
}Java 版本(迭代思路)
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
public RandomListNode Clone(RandomListNode pHead) {
if (pHead == null)
return null;
// 1. 复制节点并插入原节点之后
RandomListNode p1 = pHead;
while (p1 != null) {
RandomListNode temp = new RandomListNode(p1.label);
temp.next = p1.next;
p1.next = temp;
p1 = temp.next;
}
// 2. 复制随机指针
p1 = pHead;
while (p1 != null) {
if (p1.random != null)
p1.next.random = p1.random.next; // 易错点,需结合分析图理解
p1 = p1.next.next;
}
// 3. 拆分链表
RandomListNode head = pHead.next;
RandomListNode temp1 = head;
p1 = pHead;
while (p1.next != null) {
temp1 = p1.next;
p1.next = temp1.next;
p1 = temp1;
}
return head;
// return pHead;
}
}说明:本文题目及图解源自牛客网《剑指 Offer》经典面试题(2016 年存档)。不同在线评测系统(OJ)对递归深度或内存限制可能存在差异,实际应用中建议根据具体环境选择迭代或递归方案。
版权声明:本文为原创文章,版权归 戴老师的博客 所有,转载请联系博主获得授权。
本文地址:https://1diff.fun/archives/fu-za-lian-biao-de-fu-zhi.html
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。