复制带随机指针的链表
给定一个链表,每个结点包含一个额外增加的随机指针,该指针可以指向链表中的任何结点或空结点。要求返回这个链表的深拷贝。
示例:
输入:
{"$id":"1","next":{"$id":"2","next":null,"random":
{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}
解释:
结点 1 的值是 1,它的下一个指针和随机指针都指向结点 2.
结点 2 的值是 2,它的下一个指针指向 null,随机指针指向它自己.
提示:
必须返回给定头的拷贝作为对克隆列表的作用。
分成两步:
1.先复制所有的结点
2.处理 random 指向
简单复制无法解决(因为是浅拷贝)
需要先复制结点,后解决 random 问题
如果能从老的结点找到新的结点,问题好解决
结构:
1.老-新-老-新
2.处理 random
3.拆开
步骤:
1.把原链表变成当前形式
利用 p1 遍历原链表的每个结点
创建新结点 p2
把 p2 插入到 p1 的后边
Node p1=head;
while(p1!=null){
Node p2=new Node();
p2.val=p1.val;
p2.random=null;
p2.next=p1.next;
p1.next=p2;
p1=p2.next;
2.处理 random 指向
p1=head;
while(p1!=null){
Node p2=p1.next;
if(p1.random!=null){
p2.random=p1.random.next;
}
p1=p2.next;
}
3.拆开
p1=head;
while(p1!=null){
Node p2=p1.next;
p1.next=p2.next;
if(p2.next!=null){
p2.next=p2.next.next;
}
p1=p1.next;
}
Map
private static class NodeComparator implements Comparator<Node> {
@Override
public int compare(Node o1, Node o2) {
return o1.val - o2.val;
}
}
public static Node copyRandomList2(Node head) {
Map<Node, Node> map = new TreeMap<>(new NodeComparator());
Node newHead = null;
Node newLast = null;
Node cur = head;
while (cur != null) {
Node node = new Node();
node.val = cur.val;
if (newHead == null) {
newHead = node;
} else {
newLast.next = node;
}
newLast = node;
map.put(cur, node);
cur = cur.next;
}
cur = head;
Node node = newHead;
while (node != null) {
if (cur.random != null) {
node.random = map.get(cur.random);
} else {
node.random = null;
}
cur = cur.next;
node = node.next;
}
return newHead;
}
public class Solution {
public CNode complexCopy(CNode head) {
if (head == null) {
return null;
}
CNode p1 = head;
while (p1 != null) {
CNode p2 = new CNode(p1.val);
p2.next = p1.next;
p1.next = p2;
p1 = p2.next;
}
p1 = head;
while (p1 != null) {
CNode p2 = p1.next;
if (p1.random != null) {
p2.random = p1.random.next;
}
p1 = p2.next;
}
p1 = head;
CNode newHead = head.next;
while (p1 != null) {
CNode p2 = p1.next;
p1.next = p2.next;
if (p2.next != null) {
p2.next = p2.next.next;
}
p1 = p1.next;
}
return newHead;
}
/**
* 1. 构建几组测试数据
* 2. 进行测试
* 3. 对测试结果进行打印
* @return
*/
private static void testComplexListCopy(Solution solution) {
// 1. 构建测试数据
CNode head = createComplexList1();
// 2. 进行测试
CNode resultHead = solution.copy(head);
// 3. 对测试结果进行打印
printCList(resultHead);
}
// CNode 必须实现一个 String toString() 方法
private static void printCList(CNode head) {
for (CNode cur = head; cur != null; cur = cur.next) {
System.out.print(cur + " --> ");
}
System.out.println();
}
// CNode 必须有一个构造方法,形参是 int val
// 并且,初始化后,next 和 random 都是 null
private static CNode createComplexList1() {
CNode n1 = new CNode(1);
CNode n2 = new CNode(2);
CNode n3 = new CNode(3);
CNode n4 = new CNode(4);
n1.random = n3; n2.random = n1; n3.random = n3;
n1.next = n2; n2.next = n3; n3.next = n4;
return n1;
}
/**
* 测试面试题:
* 1)复杂链表复制
* @param args
*/
public static void main(String[] args) {
Solution solution = new Solution();
testComplexListCopy(solution);
}
}