leetcode -- Copy List with Random Pointer
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
[解题思路]
1.和clone graph那题差不多,使用一个map来保存已经创建好的node。
第一步:先复制原始链表中的节点,用next指针链接起来,在复制节点时放入map中
第二步:设置每个节点的random指针
空间复杂度为O(n),时间复杂度为O(n)
Accepted Code
1 public RandomListNode copyRandomList(RandomListNode head) { 2 // Note: The Solution object is instantiated only once and is reused by each test case. 3 if(head == null){ 4 return head; 5 } 6 7 Map<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>(); 8 RandomListNode newHead = new RandomListNode(head.label); 9 map.put(head, newHead); 10 RandomListNode p1 = head; 11 RandomListNode p2 = newHead; 12 p1 = p1.next; 13 // p2 = p2.next; 14 15 while(p1 != null){ 16 RandomListNode tmp = new RandomListNode(p1.label); 17 p2.next = tmp; 18 map.put(p1, tmp); 19 p1 = p1.next; 20 p2 = p2.next; 21 } 22 23 p1 = head; 24 p2 = newHead; 25 while(p1 != null){ 26 RandomListNode random = p1.random; 27 if(random != null) 28 p2.random = map.get(random); 29 p1 = p1.next; 30 p2 = p2.next; 31 } 32 33 return newHead; 34 }
2.上面的做法使用map的意义在于设置random指针时可以直接从map中找到,但使用map会带来O(n)的空间消耗
换个思路:第一步仍然根据原始链表的每个结点n创建相应的n'。将n'链接到n后面
第二步设置n'的random指针。n'的random指针所指向的结点是n的random指针所指向的结点的下一个结点
第三步把第二步得到的链表拆成两个链表
1 public class Solution { 2 3 public RandomListNode cloneNodes(RandomListNode head){ 4 RandomListNode p1 = head; 5 while(p1 != null){ 6 RandomListNode c1 = new RandomListNode(p1.label); 7 c1.next = p1.next; 8 p1.next = c1; 9 p1 = c1.next; 10 } 11 return head; 12 } 13 14 public RandomListNode setRandomPointer(RandomListNode head){ 15 RandomListNode p1 = head; 16 while(p1 != null){ 17 RandomListNode r1 = p1.random; 18 if(r1 != null){ 19 p1.next.random = r1.next; 20 } 21 p1 = p1.next.next; 22 } 23 return head; 24 } 25 26 public RandomListNode reconnectNodes(RandomListNode head){ 27 RandomListNode cloneHead = head.next; 28 RandomListNode p1 = head; 29 RandomListNode p2 = cloneHead; 30 while(p1 != null && p2 != null){ 31 p1.next = p2.next; 32 p1 = p1.next; 33 if(p1 != null){ 34 p2.next = p1.next; 35 } 36 p2 = p2.next; 37 } 38 return cloneHead; 39 } 40 41 public RandomListNode copyRandomList(RandomListNode head) { 42 // Note: The Solution object is instantiated only once and is reused by each test case. 43 if(head == null){ 44 return head; 45 } 46 47 cloneNodes(head); 48 setRandomPointer(head); 49 return reconnectNodes(head); 50 } 51 }
ATT:拆成两个链表时,当处理到最后一个节点时需要注意