题目意思就是说给你给head 的Node节点(这是一个比较特殊的链表),来拷贝出它地结构出来。
方法一:借助HashMap的特性,定义一个HashMap<Node,Node> map对象,key和value都是value类型 ,key来存旧的链表,value来存新的链表。最后利用老节点和新节点的对应关系来实现一个拷贝新的链表。
对于理解哈希表的同学来说,应该不难理解,code也比较容易:
/* 方法一:借助HashMap,定义一个HashMap<Node,Node> map对象,key和value都是value类型 */
public static Node copyListWithRandom1(Node head) {
HashMap<Node, Node> map = new HashMap<Node, Node>();
Node cur = head;
/* 将单链表的所有节点和value对应放进去map对象中 */
while (cur != null) {
map.put(cur, new Node(cur.value));// 这里新建一个节点,这个节点放head的value
cur = cur.next;
}
/* 重新构建链表的结构,注意,此时map对象为map<cur,cur'>,cur'为新建立的节点 */
cur = head;
/*
* 为了让大家更好的理解,我们假设旧节点和旧节点的next还有旧节点rand分别为cur,curJiu,curRand
* (不懂的同学可以先去了解一下hashMap特点)所以有:cur.next= curJiu,cur.rand= curRand
* 因此,为了保持这种结构,就有了(map.get(cur)).next = map.get(cur.next),rand同理。
*/
while (cur != null) {
map.get(cur).next = map.get(cur.next);
map.get(cur).rand = map.get(cur.rand);
cur = cur.next;
}
return map.get(head);
}
方法2:空间复杂度为O(1),只需要几个变量就可以实现,(不过个人觉得还是方法1更方便)不多说了,直接附上图:
编程如下:
/*这个方法空间复杂度为O(1),并且不用用到哈希表,相对来说容易了许多,不过思路比较巧妙,主要就是三步走*/
public static Node copyListWithRandom2(Node head) {
if (head == null) {
return null;
}
/* copy node and link to every node*/
/*从之前的1 2 3 4 5 6
* 6 6 5 3 - 4
* 变为现在的1 1 2 2 3 3 4 4 5 5 6 6
* 6 - 6 - 5 - 3 - - - 4 -
* 说到底就是添加了next指针,而rand指针不变*/
Node next = null;
Node cur = head; //每个新的操作之前都要对cur赋值
while (cur != null) {
next = cur.next; //先保存这个节点,同时也为了下面的移动方便
cur.next = new Node(cur.value);
cur.next.next = next;
cur = next;//这里千万要注意,它要往前移动
}
/*set copy node rand
* 也就是根据rand来设置新的链表的rand指针
* 从之前的1 2 3 4 5 6
* 6 6 5 3 - 4
* 变为现在的1 1 2 2 3 3 4 4 5 5 6 6
* 6 6 6 6 5 5 3 3 - - 4 4
* 说到底就是添加了rand指针*/
cur = head; //每个新的操作之前都要对cur赋值
Node curcopy = null;
while (cur != null) {
curcopy = cur.next;
/*这里要先判断cur.rand存不存在*/
if (cur.rand != null) {
curcopy.rand = cur.rand.next;
}
next = cur.next.next;
cur = next; //这里千万要注意,它要往前移动
}
/*split,将新建的链表和旧链表分离
* 断开新链表和旧链表的连接*/
cur = head; //每个新的操作之前都要对cur赋值
Node res = head.next; //定义这个节点是为了方便返回
while (cur != null) {
next = cur.next.next;
curcopy = cur.next;
cur.next = next;
/*这里要先判断curcopy.next存不存在*/
if (next != null) {
curcopy.next = next.next;
} else {
curcopy.next = null;
}
cur = next;//这里千万要注意,它要往前移动
}
return res;
}