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:拆成两个链表时,当处理到最后一个节点时需要注意


原文地址:https://www.cnblogs.com/feiling/p/3352483.html