小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
来源:力扣(LeetCode) 链接
思路
这个一道比较经典的题目,主要的难点在于random指针的处理,由于第一个节点的random可能指向后面的节点,而在复制链表的时候后面的节点还没有创建不知道random应该指向哪里,但是也可以用map存储对应的链表中节点和random指向节点的映射,然后对应去copy的链表中去操作,但是这样比较耗费空间,下面来介绍下比较常见的做法
1.在原来的链表上面进行复制,在原来链表的每个节点后面都挂上一个和该节点相同的节点,这样链表的大小就变为原来的2倍
2.对random指针进行指向
3.拆分两个链表
代码
public Node copyRandomList(Node head) {
if (head == null) return null; //如果head为空直接返回
Node temp = head; //辅助指针temp
while (temp != null) { //第一步:先对链表进行复制,就是在每个节点后面都复制一个相同的节点
Node next = temp.next; //记录next节点的位置
temp.next = new Node(temp.val); //复制节点
temp.next.next = next; //复制节点的next指向next节点
temp = next; //移动指针到next节点
}
temp = head;
while (temp != null) { //第二步:对random进行操作
temp.next.random = temp.random == null ? null : temp.random.next;
if (temp.next.next == null) break; //这边判断一下跳出,不然会出现空指针异常
temp = temp.next.next; //指针向下一个节点移动
}
//第三步: 开始拆分
temp = head;
Node temp1 = head.next;
Node head1 = temp1; //记录复制的链表的头节点的位置
while (temp != null) {
temp.next = temp.next.next; //断开链表,
if (temp.next == null) break;
temp1.next = temp.next.next;
temp = temp.next;
temp1 = temp1.next;
}
return head1;
}