Leetcode 剑指 Offer II 154. 复杂链表的复制
题目难度: 中等
原题链接
今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号算法精选里回复
剑指offer2就能看到该系列当前连载的所有文章了, 记得关注哦~
题目描述
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例 1:
- 输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
- 输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:
- 输入:head = [[1,1],[2,1]]
- 输出:[[1,1],[2,1]]
示例 3:
- 输入:head = [[3,null],[3,0],[3,null]]
- 输出:[[3,null],[3,0],[3,null]]
示例 4:
- 输入:head = []
- 输出:[]
- 解释:给定的链表为空(空指针),因此返回 null。
提示:
- -10000 <= Node.val <= 10000
- Node.random 为空(null)或指向链表中的节点。
- 节点数目不超过 1000 。
题目思考
- 如何处理 random 指针?
解决方案
思路
- 如果只有 next 指针的话很简单, 我们只需要对每个节点新建一个相同值的节点, 并保持指向关系, 逐个遍历过去即可
- 现在多了个 random 指针, 想要定位新的指向的节点, 一个比较自然的想法就是额外维护一个老节点到新节点的映射关系, 可以用字典来实现
- 第一遍遍历, 就只关注 next 部分, 并建立好映射关系
- 第二遍遍历, 考虑 random 部分, 找到对应的新链表的节点, 然后当前节点的 random 指针指向它即可
复杂度
- 时间复杂度
O(N)- 每个节点只需要遍历两次
- 空间复杂度
O(N)- 额外需要一个字典
代码
classSolution:defcopyRandomList(self,head:'Node')->'Node':ifnothead:returnNonemaps={}# 第一遍遍历, 建立新的链表, 以及老节点到新节点的映射关系copyHead=Node(head.val)origin,copy=head,copyHead maps[origin]=copywhileorigin.next:# 新建下一个节点, 并建立next关系copy.next=Node(origin.next.val)origin=origin.nextcopy=copy.nextmaps[origin]=copy# 第二遍遍历, 处理random指针部分origin,copy=head,copyHeadwhileorigin:iforigin.random:# 如果老节点random指针指向非空的话, 就将当前新节点也指向随机节点对应的新节点copy.random=maps[origin.random]origin=origin.nextcopy=copy.nextreturncopyHead大家可以在下面这些地方找到我~😊
我的 GitHub
我的 Leetcode
我的 CSDN
我的知乎专栏
我的头条号
我的牛客网博客
我的公众号: 算法精选, 欢迎大家扫码关注~😊
