本来以为只是多了个random指针,顺着新建节点就好,后来发现next建一个,random指向又建一个,会出错。
以下三种解法都来源于大佬。
今天也是没长脑子的一天呢。
第一种,先把节点都new出来,然后再挨个建立next和random指针的指向。
class Solution:
def copyRandomList(self, head):
if not head:
return None
cur=head
dic={}
#先把节点都new出来
while cur:
dic[cur]=Node(cur.val)
cur=cur.next
cur=head
#再构建next和random指向
while cur:
dic[cur].next=dic.get(cur.next) #get()返回指定键的值
dic[cur].random=dic.get(cur.random)
cur=cur.next
return dic[head]
第二种,深度优先搜索,还有广度的可以但我没copy
class Solution:
def copyRandomList(self, head):
def dfs(head):
if not head: return None
if head in visited:
return visited[head]
# 创建新结点
copy = Node(head.val, None, None)
visited[head] = copy
copy.next = dfs(head.next)
copy.random = dfs(head.random)
return copy
visited = {}
return dfs(head)
第三种,画图才看明白的,复制每个节点,此时仍然只有一个链表,只是节点重复两次,比如1->2->3变成了1->1->2->2->3->3,前一个是原有的节点,后一个是新建的节点。然后构建新节点的random指针,再然后把新老两个链表拆开,重新复制next,分成两个链表。
class Solution:
def copyRandomList(self, head):
if not head: return
cur = head
# 1. 复制各节点,并构建拼接链表
while cur:
tmp = Node(cur.val)
tmp.next = cur.next
cur.next = tmp
cur = tmp.next
#若原链表为1->2->3,则至此链表变为1->1->2->2->3->3
# 2. 再构建各新节点的 random 指向
cur = head
while cur:
if cur.random:
cur.next.random = cur.random.next
#比如1->1->2->2...其中random是2->1,第二个2指向第二个1,跳过原节点
cur = cur.next.next #原链表节点不需要重新构建random指向,跳过
# 3. 拆分两链表
cur = res = head.next #获得copy链表的头res,cur是copy链表的指针
pre = head #pre代表原节点
#copy节点和原节点都有了合适的random指向,需要拆开,重构next指向
#其中pre拆成一个链表,cur拆成一个链表
while cur.next:
pre.next = pre.next.next
cur.next = cur.next.next
pre = pre.next
cur = cur.next
pre.next = None # 单独处理原链表尾节点
#因为pre比cur靠前一个,当cur.next=None跳出循环时,pre.next实际指向了cur链表的尾节点,所以要单独赋值为None
return res # 返回新链表头节点