复杂链表的复制——牛客offer
题目描述:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
数据结构:
public class RandomListNode {
int label; 数据域
RandomListNode next = null; 指向下一个结点
RandomListNode random = null; 指向任意一个节点
RandomListNode(int label) {
this.label = label;
}
}
解题思路:
1、遍历链表,复制链表中的每个结点,并将复制的结点插入到该结点的后面。例如,原链表为A->B->C, 遍历完毕后,链表变为A->A'->B->B'->C->C',其中A‘,B',C'是结点A,B,C的复制结点。
看图中,蓝色箭头为next指针:
复制结点后:
2、为复制结点的random指针赋值
如果原结点的random指针指向的是结点B,那么将复制结点的random指针指向结点B的复制结点B'。
图中黑色箭头为random指针:
复制结点的random指针赋值后:
3、将链表的原始结点与复制结点分割至两个链表,使原始结点构成一个链表,复制结点构成一个链表。
代码实现:
1、复制结点
//1.加入copy结点
public void copyNodes(RandomListNode pHead){
RandomListNode walkNode=pHead;
while(walkNode!=null){
RandomListNode cloneNode=new RandomListNode(walkNode.label);
cloneNode.next=walkNode.next;
walkNode.next=cloneNode;
walkNode=cloneNode.next;
}
}
2、为复制结点的random指针域赋值
//2.为新copy结点的random域指定值
public void initRandom(RandomListNode pHead){
RandomListNode walkNode=pHead;
RandomListNode cwalkNode=pHead;
while(walkNode!=null){
cwalkNode=walkNode.next;
if(walkNode.random!=null){
cwalkNode.random=walkNode.random.next;
}
walkNode=cwalkNode.next;
}
}
3、将结点和复制结点分为两个链表
//3.将链表和其copy版本分为两个链表
public RandomListNode split2list(RandomListNode pHead){
RandomListNode cpHead=pHead.next;
RandomListNode walkNode=pHead;
RandomListNode cwalkNode=cpHead;
while(walkNode!=null){
walkNode.next=cwalkNode.next;
walkNode=walkNode.next;
if(walkNode==null){
cwalkNode.next=null;
}
else{
cwalkNode.next=walkNode.next;
cwalkNode=cwalkNode.next;
}
}
return cpHead;
}
4、总的调用函数
public RandomListNode Clone(RandomListNode pHead)
{
if(pHead==null){
return null;
}
copyNodes(pHead);
initRandom(pHead);
return split2list(pHead);
}
全部代码
1 class RandomListNode {
2 int label;
3 RandomListNode next = null;
4 RandomListNode random = null;
5 RandomListNode(int label) {
6 this.label = label;
7 }
8 }
9
10 public class copyList {
11 //1.加入copy结点
12 public void copyNodes(RandomListNode pHead){
13 RandomListNode walkNode=pHead;
14 while(walkNode!=null){
15 RandomListNode cloneNode=new RandomListNode(walkNode.label);
16 cloneNode.next=walkNode.next;
17 walkNode.next=cloneNode;
18 walkNode=cloneNode.next;
19 }
20 }
21 //2.为新copy结点的random域指定值
22 public void initRandom(RandomListNode pHead){
23 RandomListNode walkNode=pHead;
24 RandomListNode cwalkNode=pHead;
25 while(walkNode!=null){
26 cwalkNode=walkNode.next;
27 if(walkNode.random!=null){
28 cwalkNode.random=walkNode.random.next;
29 }
30 walkNode=cwalkNode.next;
31 }
32 }
33 //3.将链表和其copy版本分为两个链表
34 public RandomListNode split2list(RandomListNode pHead){
35 RandomListNode cpHead=pHead.next;
36 RandomListNode walkNode=pHead;
37 RandomListNode cwalkNode=cpHead;
38 while(walkNode!=null){
39 walkNode.next=cwalkNode.next;
40 walkNode=walkNode.next;
41 if(walkNode==null){
42 cwalkNode.next=null;
43 }
44 else{
45 cwalkNode.next=walkNode.next;
46 cwalkNode=cwalkNode.next;
47 }
48 }
49 return cpHead;
50 }
51 public RandomListNode Clone(RandomListNode pHead)
52 {
53 if(pHead==null){
54 return null;
55 }
56 copyNodes(pHead);
57 initRandom(pHead);
58 return split2list(pHead);
59 }
60 public static void main(String[]args){
61 RandomListNode head = new RandomListNode(1);
63 RandomListNode node2 = new RandomListNode(2);
65 RandomListNode node3 = new RandomListNode(3);
67 RandomListNode node4 = new RandomListNode(4);
69 RandomListNode node5 = new RandomListNode(5);
70 head.next = node2;
71 node2.next = node3;
72 node3.next = node4;
73 node4.next = node5;
74 head.random = node3;
75 node2.random = node5;
76 node4.random = node2;
77 copyList s = new copyList();
78 RandomListNode copyList=s.Clone(head);
79 System.out.print(copyList.label + " ");
80 // while (copyList != null)
81 // {
82 // System.out.print(copyList.label + " ")
83 // copyList = copyList.next;
84 // }
85 }
86 }