剑指offer面试题26:复杂链表的复制
题目:请实现一个函数,复制一个复杂链表。
在复杂链表中,每个结点除了有一个next指针指向下一个结点外,还有一个sibling指针指向链表中的任意结点或者nulL
直观解法:
1.遍历链表,复制链表节点,并连接next节点。2.遍历链表,连接sibling节点。对于一个有n个节点的链表,由于定位每个节点的silbing节点都需要从链表的头结点开始经过O(n)步才能实现,因此这种方法的时间复杂度是O(n2)
优化解法:上述方法的时间主要是用在了sibling节点的定位上,考虑优化此步骤。具体的做法是在复制节点的时候,把原节点N和复制出来的N'节点用一个map保存起来,这样在第二部连接sibling结点的时候就可以以O(1)的时间复杂度定位到相应的sibling节点,总体时间复杂度为O(n),空间复杂度也是O(n)
最优算法:
第一步:根据原始链表的每个节点创建对应的复制结点,把复制结点连接在原结点的后面
第二步:设置复制出来的结点的任意结点sibling节点
第三步:把长链表拆分成两个链表
1 package Solution; 2 3 public class No26CopyComplexList { 4 5 static class ComplexListNode{ 6 int value; 7 ComplexListNode next; 8 ComplexListNode sibling; 9 public ComplexListNode(){ 10 11 } 12 public ComplexListNode(int value,ComplexListNode next,ComplexListNode sibling){ 13 this.value=value; 14 this.next=next; 15 this.sibling=sibling; 16 } 17 } 18 19 //把复杂链表中的所有结点进行复制,并连接在原结点的后面 20 private static void cloneNode(ComplexListNode head){ 21 ComplexListNode node=head; 22 while(node!=null){ 23 ComplexListNode clonedNode=new ComplexListNode(); 24 clonedNode.value=node.value; 25 clonedNode.next=node.next; 26 clonedNode.sibling=null; 27 node.next=clonedNode; 28 node=clonedNode.next; 29 } 30 } 31 //设置复制的节点的指向任意结点的连接关系 32 private static void connectSiblingNodes(ComplexListNode head){ 33 ComplexListNode node=head; 34 while(node!=null){ 35 ComplexListNode clonedNode=node.next; 36 if(node.sibling!=null){ 37 clonedNode.sibling=node.sibling.next; 38 } 39 node=clonedNode.next; 40 } 41 } 42 //把长链表拆分成两个单独的链表,并返回复制后的链表的头结点 43 private static ComplexListNode reconnectNodes(ComplexListNode head){ 44 ComplexListNode node=head; 45 ComplexListNode clonedHead=null; 46 ComplexListNode clonedNode=null; 47 if(node!=null){ 48 clonedHead=clonedNode=node.next; 49 node.next=clonedNode.next; 50 node=clonedNode.next; 51 } 52 while(node!=null){ 53 clonedNode.next=node.next; 54 clonedNode=node.next; 55 node.next=clonedNode.next; 56 node=clonedNode.next; 57 } 58 return clonedHead; 59 } 60 public static ComplexListNode copyComplexList(ComplexListNode head){ 61 if(head==null) 62 return null; 63 cloneNode(head); 64 connectSiblingNodes(head); 65 return reconnectNodes(head); 66 } 67 68 public static void printComplexList(ComplexListNode head){ 69 ComplexListNode node=head; 70 int value=0; 71 ComplexListNode next=null; 72 ComplexListNode sibling=null; 73 while(node!=null){ 74 value=node.value; 75 next=node.next; 76 sibling=node.sibling; 77 StringBuilder sb=new StringBuilder("当前节点的值为:").append(value); 78 if(next!=null) 79 sb.append(",下一结点的值为:").append(next.value); 80 else 81 sb.append(",当前结点为尾节点"); 82 if(sibling!=null) 83 sb.append(",指向任意结点的值为:").append(sibling.value); 84 else 85 sb.append(",没有指向其他结点的任意结点"); 86 System.out.println(sb.toString()); 87 node=node.next; 88 } 89 } 90 public static void main(String[] args) { 91 ComplexListNode node1=new ComplexListNode(); 92 ComplexListNode node2=new ComplexListNode(); 93 ComplexListNode node3=new ComplexListNode(); 94 ComplexListNode node4=new ComplexListNode(); 95 ComplexListNode node5=new ComplexListNode(); 96 node1.value=1; 97 node1.next=node2; 98 node1.sibling=node3; 99 node2.value=2; 100 node2.next=node3; 101 node2.sibling=node5; 102 node3.value=3; 103 node3.next=node4; 104 node3.sibling=null; 105 node4.value=4; 106 node4.next=node5; 107 node4.sibling=node2; 108 node5.value=5; 109 node5.next=null; 110 node5.sibling=null; 111 printComplexList(node1); 112 System.out.println("=========================开始复制============================"); 113 printComplexList(copyComplexList(node1)); 114 } 115 }