8.<tag-链表和哈希表, >lc-138. 复制带随机指针的链表
lc-138. 复制带随机指针的链表
[案例需求]

[思路分析一, HashMap 存储法]
本题其实解题方法有挺多的, 以后再补吧, 先把这个学费!
- 前面曾经提到过, 对于链表结点, 因为链式存储的原因, 我们无法通过索引随机访问而只能遍历访问, 相比于数组, 链表的遍历可真是太让人难受了
- 所以有些题目, 我们经常会使用各种特性的集合来存储链表结点, 在一定程度上提高链表访问的遍历性. 比如前面写过的题解": 7.<tag-链表和反转, 求中间结点, 合并有序链表>lt.143-重排链表, 就利用了list可以随机访问的特性, 通过一次链表遍历, 把结点放到list中, 然后通过list 的索引访问(list.get(index))来进行下一步的前半部分和后半部分的合并工作;
- 对于本题: 其实重点就在于如何对原有的链表进行深拷贝. 同时也把原有链表每个节点的next域, 和radom域拷贝到新结点中;
- 我们可以这么做:
- 把原有链表的每个节点存储到HashMap中, 为什么是Map呢? 目的就是让旧结点和新节点一一对应, 所以键值对为: <旧结点, 新结点>
- 第一次我们先遍历原来的链表, 把遇到的结点作为map的key, 同时以这个旧结点的val为参数新建一个新节点作为key的value, 即<旧结点, new Node(旧结点.val); 这样的话每个旧结点都有一个新节点与之对应;
- 第二次再去遍历旧结点, 这一次我们要把新节点的next域和random域组合起来,
新节点.next = map.get(旧结点.next)新节点.random = map.get(旧结点.random)- 注意噢, 新节点 = map.get(旧结点)
[代码实现]
/*
// Definition for a Node.
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) {
//
//遍历原有链表, 每遍历一个结点都新建一个相同val 的结点, 然后使用Hashmap存放于<原链表结点, 新链表结点>
// 再一次遍历链表, 通过hashMap, 建立起新链表的之间的next, random关系
Map<Node, Node> map = new HashMap<>();
Node temp = head;
while(true){
if(temp == null)break;
map.put( temp, new Node(temp.val));
temp = temp.next;
}
//再一次遍历
temp = head;
while(true){
if(temp == null)break;
map.get(temp).next = map.get(temp.next);
map.get(temp).random = map.get(temp.random);
temp = temp.next;
}
return map.get(head);
}
}

浙公网安备 33010602011771号