复制带随机指针的链表
复制带随机指针的链表
作者:Grey
原文地址:
题目描述
一种特殊的单链表节点类描述如下
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
random 指针是单链表节点结构中新增的指针,random 可能指向链表中的任意一个节点,也可能指向 null,
给定一个由 Node 节点类型组成的无环单链表的头节点 head,请实现一个函数完成这个链表的复制,返回复制的新链表的头节点。
注:要求时间复杂度O(N),额外空间复杂度O(1)
OJ见:LeetCode 138. Copy List with Random Pointer
主要思路
假设原始链表如下,其中虚线表示 random 指针
由于空间复杂度需要O(1)
,所以使用辅助数组的方式不可取,只能在链表上进行原地调整。
第一步,将当前节点的复制节点连在当前节点的下一个位置上,如上链表,a'
为a
的复制节点,其他节点同理,首先会得到如下链表
第二步,复制节点的 random 指针指向当前节点的 random 指针的下一个位置,以a
节点为例,a
节点的next
就是a
的复制节点a'
,a
节点的random
节点的next
就是a'
的random
指针
即a.next.random = a.random.next
,由于random
指针可能为空,所以a.next.random = a.random == null?null:a.random.next
,其余节点类似,示例图如下
第三步,以上已经完成了链表元素的复制,接下来是分离原链表和复制链表。
以a
和a'
节点为例,分离的过程就是
a.next = a.next.next;
a'.next = a'.next.next;
特别要注意最后一个节点,因为最后一个节点的next
为空,所以,针对最后一个节点d
和d'
来说
d.next = null;
d'.next = null;
最后返回复制链表的头部即可,本例中,返回a'
节点即可。
完整代码见
/*
// 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) {
if (head == null) {
return head;
}
Node cur = head;
// 复制节点接在当前节点的后面
while (cur != null) {
Node next = cur.next;
Node copy = new Node(cur.val);
cur.next = copy;
copy.next = next;
cur = next;
}
// 设置复制节点的random指针
cur = head;
while (cur != null) {
cur.next.random = cur.random == null ? null : cur.random.next;
cur = cur.next.next;
}
cur = head;
// 切割原链表和复制链表
Node newHead = cur.next;
cur = head;
Node copyCur = newHead;
while (cur != null) {
cur.next = cur.next.next;
copyCur.next = copyCur.next == null ? null:copyCur.next.next;
cur = cur.next;
copyCur = copyCur.next;
}
return newHead;
}
}
本题的所有图例见: processon:复制带随机指针的链表
更多
本文来自博客园,作者:Grey Zeng,转载请注明原文链接:https://www.cnblogs.com/greyzeng/p/16750999.html