package com.example.lettcode.offer;
import java.util.HashMap;
import java.util.Map;
/**
* @Class CopyRandomList
* @Description 剑指 Offer 35. 复杂链表的复制
* 请实现 copyRandomList 函数,复制一个复杂链表。
* 在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,
* 还有一个 random 指针指向链表中的任意节点或者 null。
*
* 提示:
* -10000 <= Node.val <= 10000
* Node.random 为空(null)或指向链表中的节点。
* @Author
* @Date 2020/7/6
**/
public class CopyRandomList {
static class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
}
/**
* 解法1: 先逐个设置复制链表每个节点的next指针
* 再设置每个节点的random指针,复制random指针时,都需要从头结点还是寻找
*/
public static Node copyRandomList(Node head) {
if (head == null) return head;
Node p = head;
Node neHead = new Node(head.val);
Node q = neHead;
// 先找到对应的next
while (p != null) {
Node node = new Node(p.val);
q.next = node;
q = q.next;
p = p.next;
}
p = head;
q = neHead.next;
// 再设置复制链表的random指针
while (p != null) {
Node tempP = head;
Node tempQ = neHead.next;
// random 需要从头开始重新遍历
while (tempP != p.random && tempP != null) {
tempP = tempP.next;
tempQ = tempQ.next;
}
q.random = tempQ;
p = p.next;
q = q.next;
}
return neHead.next;
}
/**
* 解法2: 利用HashMap,保存每个节点和其对应的复制节点,以便next和random指针可以直接
*/
public static Node copyRandomList(Node head) {
if (head == null) return head;
Map<Node, Node> nodeNodeMap = new HashMap<>();
Node node = head;
while (node != null) {
nodeNodeMap.put(node, new Node(node.val));
node = node.next;
}
/* 方式1
//复制结点指向
node = head;
while (node != null) {
//新结点next指向同旧结点的next指向
nodeNodeMap.get(node).next = nodeNodeMap.get(node.next);
//新结点random指向同旧结点的random指向
nodeNodeMap.get(node).random = nodeNodeMap.get(node.random);
node = node.next;
}
// 返回旧链表head 所对应的复制结点
return nodeNodeMap.get(head);*/
// 方式2
node = head;
// 注释的这一行新建了一个头结点,导致这个头结点的random是null,
// 并非是nodeNodeMap 中head节点对应的复制后的头结点
// Node newHead = new Node(head.val);
Node newHead = nodeNodeMap.get(head);
Node cur = newHead;
while (node != null) {
cur.next = nodeNodeMap.get(node.next);
cur.random = nodeNodeMap.get(node.random);
node = node.next;
cur = cur.next;
}
return newHead;
}
// 测试用例
public static void main(String[] args) {
Node head = new Node(7);
Node node11 = new Node(13);
head.next = node11;
node11.random = head;
Node node12 = new Node(11);
node11.next = node12;
Node node13 = new Node(10);
node12.next = node13;
node13.random = node12;
Node node14 = new Node(1);
node13.next = node14;
node12.random = node14;
node14.random = head;
Node copyHead = copyRandomList(head);
System.out.println("");
}