题目描述:
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
1)节点的引用保存的只是地址值,需要重写toString方法才能将引用的具体内容进行输出;
2)链表问题:操作的仍然只是单独的一个节点;只是节点中含有节点类型的变量,可以存储地址寻找下一个节点,逻辑上成为了一个不连续的链;
考察深拷贝的知识点。
答案中用到的Map:哈希表的特点,一一映射的关系,用Key找到Value(准确找到),先一一对应的创建出节点,再用Key取到新创建的节点进行连接。
map.get(key)得到value值
哈希表中放对象,对象作为Key值来进行Value的寻找。
自己能想到的方式:
1.创建一个新的链表,逐项将head中的内容连接到新的链表上,错误!可以当作正常链表的复制
答案解析说到,不能直接创建新链表复制,是因为会出现 随机节点还未创建的情况!「当前节点的随机指针指向的节点」可能还没创建
还是不太能理解
重点是先将节点都创建出来,再进行引用指向,此时就不会出现找不到随机random节点的情况。
class Solution {
public Node copyRandomList(Node head) {
Node newNode = new Node(0);//和head不同位置
Node cur = newNode;//记录了相同的地址值,可以通过该地址值找到新的链表
while(head != null){
Node next = head.next;//拿到下一个节点
//复制操作
cur.val = head.val;
cur.next = head.next;
cur.random = head.random;
head = next;
cur = cur.next;
}
return newNode;
}
}
答案代码:问题的关键就是 不管random,先将所有的节点构建出来,再进行连接。
1.哈希表:
class Solution {
public Node copyRandomList(Node head) {
if(head == null) return null;
Map<Node,Node> map = new HashMap<Node,Node>();
Node cur = head;
//创建哈希表,将需要连接的节点先创建出来,此时引用未指向,说明next和random都是null
while(cur != null){
map.put(cur,new Node(cur.val));
cur = cur.next;
}
//进行引用关系的连接
cur = head;
while(cur != null){
//map.get(cur).next = cur.next; 应该指向新创建的节点
//map.get(cur).random = cur.random;
map.get(cur).next = map.get(cur.next);
map.get(cur).random = map.get(cur.random);
cur = cur.next;
}
return map.get(head);
}
}
作者:jyd
链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/jian-zhi-offer-35-fu-za-lian-biao-de-fu-zhi-ha-xi-/
来源:力扣(LeetCode)
哈希+回溯
class Solution {
Map<Node, Node> cachedNode = new HashMap<Node, Node>();
public Node copyRandomList(Node head) {
if (head == null) {
return null;
}
if (!cachedNode.containsKey(head)) {
//没有该节点,就先创建
Node headNew = new Node(head.val);
cachedNode.put(head, headNew);
//进行引用的指向,回溯;
//回溯为了避免random还未创建,如果哈希表中有直接返回,如果没有就创建
headNew.next = copyRandomList(head.next);
headNew.random = copyRandomList(head.random);
}
return cachedNode.get(head);
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/fu-za-lian-biao-de-fu-zhi-by-leetcode-so-9ik5/
来源:力扣(LeetCode)
2. 拆分+拼接
class Solution {
public Node copyRandomList(Node head) {
if(head == null) return null;
Node cur = head;
// 1. 复制各节点,并构建拼接链表
while(cur != null) {
Node tmp = new Node(cur.val);
tmp.next = cur.next;
cur.next = tmp;
cur = tmp.next;
}
// 2. 构建各新节点的 random 指向
cur = head;
while(cur != null) {
if(cur.random != null)
cur.next.random = cur.random.next;
cur = cur.next.next;
}
// 3. 拆分两链表
cur = head.next;
Node pre = head, res = head.next;
while(cur.next != null) {
pre.next = pre.next.next;
cur.next = cur.next.next;
pre = pre.next;
cur = cur.next;
}
pre.next = null; // 单独处理原链表尾节点
return res; // 返回新链表头节点
}
}
作者:jyd
链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/jian-zhi-offer-35-fu-za-lian-biao-de-fu-zhi-ha-xi-/
来源:力扣(LeetCode)