示例:
输入:{1,2,3,4,5,3,5,#,2,#}
输出:{1,2,3,4,5,3,5,#,2,#}
解析:我们将链表分为两段,前半部分{1,2,3,4,5}为ListNode,后半部分{3,5,#,2,#}是随机指针域表示。
以上示例前半部分可以表示链表为的ListNode:1->2->3->4->5
后半部分,3,5,#,2,#分别的表示为
1的位置指向3,2的位置指向5,3的位置指向null,4的位置指向2,5的位置指向null
如下图:
第一种解法,借助一个辅助工具,借助一个map,第一次循环遍历链表,将每个节点和节点的复制值作为key和value放进map里面。第二次遍历链表,将每个节点都作为key去map中查询节点,获得当前节点的 random,并且复制给当前复制节点的random指针。代码如下
public RandomListNode firstClone(RandomListNode pHead) {
if(null == pHead){
return null;
}
HashMap<RandomListNode, RandomListNode> map = new HashMap<>();
RandomListNode randomListNode = new RandomListNode(pHead.label);
RandomListNode head = pHead;
RandomListNode cloneHead = randomListNode;
map.put(head,cloneHead);
while (null != head.next){
cloneHead.next = new RandomListNode(head.next.label);
head = head.next;
cloneHead = cloneHead.next;
map.put(head,cloneHead);
}
head = pHead;
cloneHead = randomListNode;
while (null != cloneHead){
cloneHead.random = map.get(head.random);
head = head.next;
cloneHead = cloneHead.next;
}
return randomListNode;
}
第二种解法,简称双节点解法,顾名思义,就是在复制节点的时候,将复制节点放在当前节点的后面,复制节点random就是当前节点random,这样操作之后,就是每个节点都存在双份,结果按奇或偶拆分链表即可。结合代码画个图给大家,方便大家,也方便自己加强理解,代码如下
while (null != head){
RandomListNode node = new RandomListNode(head.label);
node.next = head.next;
head.next = node;
head = node.next;
}
上面这段代码执行以后,如下图
while (null != head && null != head.next){
if(null != head.random){
head.next.random = head.random.next;
}
//因为每个节点后面跟了一个复制节点,所以需要跳两级
head = head.next.next;
}
上面这段代码执行之后,如下图
while (null != head && null != head.next){
head.next = head.next.next;
if(null == head.next){
result.next = null;
}else {
result.next = head.next.next;
}
result = result.next;
head = head.next;
}
此代码就是对处理过的链表进行拆分,如下图
完整代码如下
public RandomListNode secondClone(RandomListNode pHead) {
if (null == pHead) {
return null;
}
RandomListNode head = pHead;
while (null != head){
RandomListNode node = new RandomListNode(head.label);
node.next = head.next;
head.next = node;
head = node.next;
}
head = pHead;
while (null != head && null != head.next){
if(null != head.random){
head.next.random = head.random.next;
}
//因为每个节点后面跟了一个复制节点,所以需要跳两级
head = head.next.next;
}
RandomListNode resultHead = pHead.next;
head = pHead;
RandomListNode result = resultHead;
//拆分链表
while (null != head && null != head.next){
head.next = head.next.next;
if(null == head.next){
result.next = null;
}else {
result.next = head.next.next;
}
result = result.next;
head = head.next;
}
return resultHead;
}