Acwing 48. 复杂链表的复刻
原题链接
请实现一个函数可以复制一个复杂链表。
在复杂链表中,每个结点除了有一个指针指向下一个结点外,还有一个额外的指针指向链表中的任意结点或者null。
注意:
函数结束后原链表要与输入时保持一致。
数据范围
链表长度 [0,500]。
代码案例:
题解
哈希表做法和更加巧妙的解法
主要思路是通过复制链表的方式,来解决random节点的查找问题。大体可以分为三步:
- 链表所有节点中间都插入一个复制节点,作为并行链表
- 遍历新链表,遇到Random节点后对应改变并行链表中的节点
- 提取出并行链表
写法精简一点
public ListNode copyRandomList(ListNode head) {
if(head == null){
return null;
}
for(ListNode cur = head; cur != null; cur = cur.next.next){
ListNode temp = new ListNode(cur.val);
temp.next = cur.next;
cur.next = temp;
}
for(ListNode cur = head; cur != null; cur = cur.next.next){
if(cur.random == null){
continue;
}
cur.next.random = cur.random.next;
}
ListNode newHead = new ListNode(-1);
for(ListNode cur = head, cur1 = newHead; cur != null; cur = cur.next){
cur1.next = cur.next;
cur1 = cur1.next;
cur.next = cur.next.next;
}
return newHead.next;
}
/**
* Definition for singly-linked list with a random pointer.
* class ListNode {
* int val;
* ListNode next, random;
* ListNode(int x) { this.val = x; }
* };
*/
class Solution {
public ListNode copyRandomList(ListNode head) {
//第一步 复制原来的结点 在每个结点的后面
ListNode p ;
for( p = head ; p != null ;p=p.next.next){
ListNode t = new ListNode(p.val);
ListNode tt = p.next ;//复制结点的时候留存p.next结点 要不动用p.next 会导致结果为空
p.next = t ;
t.next = tt ;
// p = tt;//如果是p = p.next 的话那么p就是代替的是复制的t结点了 而我们是要遍历原来的结点 要替代原来的结点
//或者改成p = p.next.next
}
//第二步 random指向
p = head ;
while( p != null ){
if(p.random != null)
p.next.random = p.random.next;
p = p.next.next;
}
//第三步 遍历结点 要把复制结点拎出来
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
//dummy.next = head ;
for( p = head ; p != null ; p = p.next){
cur.next = p.next ;
cur = cur.next ;//把cur 往后移一个位置
p.next =p.next.next ;//p.next 往后移一个位置
}
return dummy.next;
}
}
借助HashMap[HTML_REMOVED],key= 以前的结点 value = 新复制的结点
先从前往后将链表复制出来,再一一修改其random指针。
public ListNode copyRandomList(ListNode head) {
if(head == null){
return null;
}
Map<ListNode, ListNode> map = new HashMap<>(); // key = old value = new
ListNode newHead = new ListNode(head.val);
map.put(head, newHead);
for(ListNode cur1 = head, cur2 = newHead; cur1.next != null; cur1 = cur1.next, cur2 = cur2.next){
cur2.next = new ListNode(cur1.next.val);
map.put(cur1.next, cur2.next);
}
for(ListNode cur1 = head, cur2 = newHead; cur1 != null; cur1 = cur1.next, cur2 = cur2.next){
if(cur1.random == null){
continue;
}
cur2.random = map.get(cur1.random);
}
return newHead;
}