描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)。 下图是一个含有5个结点的复杂链表。图中实线箭头表示next指针,虚线箭头表示random指针。为简单起见,指向null的指针没有画出。
示例
输入:{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
如下图:
思路
因为这是一道算法题,所以出题人不允许直接返回非pHead。
此算法分为三个部分:
1. forward复制label(val),并且将复制值按在原指针后面
2. 创建复制的random指针
3. 将复制指针从原指针剥离
接下来,详细讲解
1. forward复制label(val),并且将复制值按在原指针后面
若原链表为:
排除random指针带来的干扰,将原链表视为只有next指针的链表:
则,完成1. 复制指针并将其插入原指针对应位置后 操作后链表会变为:
此过程,拆解为:
(1) clone = RandomListNode(cur.label)
(2) clone.next = cur.next
(3) cur.next = clone
(4) cur = clone.next
2.创建复制的random指针
接1. 操作 将链表还原成:
则,完成2. 创建复制的random指针后 操作后链表会变为:
此过程,拆解为:
若求 橙色1(cur.next)的random指针橙色3(cur.next.random),已知蓝色1(指针cur) 的random指针是蓝色3(cur.random),且蓝色指针相对于橙色指针是.next。
所以 cur.next.random = cur.random.next
接着cur走两步,从蓝色的1走到蓝色的2
cur = cur.next.next
3. 将复制指针从原指针剥离
则,完成3. 将复制指针从原指针剥离后 操作后链表会变为:
(1) cur = pHead
newHead = pHead.next
将pHead与newHead分开
(2) temp = cur.next
cur.next = temp.next
cur = temp
代码
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
if pHead == None:
return None
# 1. copy label
cur = pHead
while cur:
clone = RandomListNode(cur.label)
clone.next = cur.next
cur.next = clone
cur = clone.next
# 2. create random
cur = pHead
while cur:
if cur.random:
cur.next.random = cur.random.next
cur = cur.next.next
# 3. divide RandomListNode
cur = pHead
newHead = pHead.next
while cur.next:
temp = cur.next
cur.next = temp.next
cur = temp
return newHead
结果