题目描述
思路
-
复制简单单向链表时,可以直接复制。
-
这个提,对某一个节点来说,要复制两个东西,所以可能会重复复制。比如前面的节点已经复制6作为他的random,恰好当前节点的next也是6,就不能再复制了,应该直接指向之前复制的6.
cur.randomcur.next
-
解决方法:用Map<原链表中的节点,新链表中对应位置上的节点>来记录哪些node已经被添加过了,在add cur.next和cur.random前先判断是否已经存在要添加的节点,如果存在,直接get(对应位置上的旧节点),如果不存在再new一个。
方法一 直接复制
class Solution {
public Node copyRandomList(Node head) {
if (head == null) return head;
// 复制各个node
Node cur = head;
while (cur != null) {
Node newNode = new Node(cur.val);
newNode.next = cur.next;
cur.next = newNode;
cur = cur.next.next;
}
// 复制 random 指针
cur = head;
while (cur != null) {
Node random = cur.random;
cur.next.random = random == null ? null : random.next;//
cur = cur.next.next;
}
// disconnect copied with original
Node newHead = head.next;
Node cur1 = head, cur2 = newHead; //
while (cur1.next != null && cur2.next != null) {
cur1.next = cur1.next.next; // order
cur2.next = cur2.next.next;
cur1 = cur1.next;
cur2 = cur2.next;
}
cur1.next = null; // 画个图
return newHead;
}
}
方法二 map
- map<old, new>
- 先拷贝一个新的头节点
cur1.next.val,cur1.random.val需要判断一下是否为空
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
class Solution {
public Node copyRandomList(Node head) {
if (head == null) {
return head;
}
Node newHead = new Node(head.val);//复制一个新头
Map<Node, Node> map = new HashMap<>();//map中放<旧节点,新节点>
map.put(head, newHead);
Node cur1 = head;//cur1为原链表指针
Node cur2 = newHead;//cur2为新链表指针
while (cur1 != null) {
//当前节点的next节点还没有在新list中被添加过
if (map.get(cur1.next) == null) {
Node nxt = cur1.next == null ? null : new Node(cur1.next.val);//注意cur.next=null的情况
cur2.next = nxt;
map.put(cur1.next, cur2.next);
} else {
cur2.next = map.get(cur1.next);
}
//当前节点的random节点还没有在新list中被添加过
if (map.get(cur1.random) == null) {
Node rdm = cur1.random == null ? null : new Node(cur1.random.val);//注意cur.next=null的情况
cur2.random = rdm;
map.put(cur1.random, cur2.random);
} else {
cur2.random = map.get(cur1.random);
}
cur1 = cur1.next;
cur2 = cur2.next;
}
return newHead;
}
}