題目描述:
輸入一個復雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果為復制后復雜鏈表的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 }