含有随机指针节点,是指这个链表不仅含有next指着,指向下一个节点,还含有rand指针,随机指向本链表中的一个节点,被指向的节点可以在本节点之前,也可以在本节点之后;
本题需要复制这样一个含有随机指针节点的链表。
解1:使用HashMap,时间复杂度为O(N),空间复杂度为O(N)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 public class RandNode { 2 int val; 3 RandNode rand; 4 RandNode next; 5 6 public RandNode(int val){ 7 this.val=val; 8 } 9 10 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // 复制一个含有随机指针节点的链表 2 public static RandNode copyListWithRand1(RandNode head){ 3 if(head==null) 4 return null; 5 // hashmap将rand指针的next对应关系存起来 6 HashMap<RandNode, RandNode> nodeMap = new HashMap<RandNode, RandNode>(); 7 RandNode cur = head; 8 while(cur != null){ 9 nodeMap.put(cur, new RandNode(cur.val)); 10 cur = cur.next; 11 } 12 13 // 建立next和rand的对应关系 14 cur = head; 15 while(cur != null){ 16 nodeMap.get(cur).next = nodeMap.get(cur.next); 17 nodeMap.get(cur).rand = nodeMap.get(cur.rand); 18 cur = cur.next; 19 } 20 return nodeMap.get(head); 21 }
解2:时间复杂度为O(N),空间复杂度为O(1)
遍历链表,将当前遍历的节点,创建副本copy,将copy链接到当前节点和下一次遍历的节点之间;
将副本节点的rand指针指向正确位置;
拆分原来的链表和新复制的链表;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // 复制一个含有随机指针节点的链表,解法2 2 public static RandNode copyListWithRand2(RandNode head){ 3 if(head==null) 4 return head; 5 6 // 先遍历链表,同时复制此链表,将每个节点的副本copy,放在本节点和下一个遍历的节点之间 7 RandNode cur = head; 8 while (cur!=null){ 9 RandNode copy = new RandNode(cur.val); 10 copy.next = cur.next; 11 cur.next = copy; 12 cur = copy.next; 13 } 14 15 // 在遍历链表,将副本的rand指针链接起来 16 cur = head; 17 while(cur != null){ 18 if(cur.rand != null){ 19 cur.next.rand = cur.rand.next; 20 } 21 cur = cur.next.next; 22 } 23 24 // 拆分链表 25 RandNode rs = head.next; 26 RandNode newCur; 27 cur = head; 28 29 while(cur != null){ 30 newCur = cur.next; 31 cur.next = newCur.next; //下一轮的第一个 32 if(cur.next != null) 33 newCur.next = cur.next.next; 34 else 35 newCur.next = null; 36 cur = cur.next; 37 } 38 39 return rs; 40 }