题目描述
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
题目分析
题中每个节点新增了 random 指针,指向链表中的 任意节点 或者 空 。这个 random 指针就意味着在复制时,除了基础的结点创建 ,还需要创建节点中的 pre.random指针及其指向的节点 。
本题难点
在复制链表的过程中构建新链表各节点的 random 引用指向。

解题
哈希映射
可以将原节点与新节点进行哈希映射,然后再查哈希表去构建每个节点的random指针。时间复杂度O(n) 空间复杂度O(n)
/**
* Definition for a Node.
* type Node struct {
* Val int
* Next *Node
* Random *Node
* }
*/
// 哈希表映射 时间复杂度O(n) 空间复杂度O(n)
func copyRandomList(head *Node) *Node {
if head == nil {
return head
}
// 新建链表,并将其与原链表结点映射
nodeMap := make(map[*Node]*Node, 10)
var newHead *Node
var newCur *Node
cur := head
for cur != nil {
node := new(Node)
node.Val = cur.Val
nodeMap[cur] = node
cur = cur.Next
if newCur == nil{
newHead = node
newCur = newHead
continue
}
newCur.Next = node
newCur = newCur.Next
}
// 建立random关系
cur = head
newCur = newHead
for cur != nil {
newCur.Random = nodeMap[cur.Random]
newCur = newCur.Next
cur = cur.Next
}
return newHead
}
衍生+拼接
可以先遍历一遍初始链表,在每个节点后衍生一个新节点,在创建新链表时,新节点的random指向的就是原节点random所指结点后的衍生结点。
初始链表

衍生结点

拆分还原链表
- 构建radom指向

- 拆分并还原链表

- 全部拆分并还原

代码实现
/**
* Definition for a Node.
* type Node struct {
* Val int
* Next *Node
* Random *Node
* }
*/
// 拼装+分解
func copyRandomList(head *Node) *Node {
if head == nil {
return head
}
// 拼接子节点,在源节点后衍生新节点
cur := head
for cur != nil {
node := new(Node)
node.Val = cur.Val
nextNode := cur.Next
node.Next = nextNode
cur.Next = node
cur = nextNode
}
// 建立新节点random指向
cur = head
for cur != nil {
nextNode := cur.Next
if cur.Random != nil {
nextNode.Random = cur.Random.Next
}
cur = nextNode.Next
}
// 将子节点从原链表中分离
cur = head
var newHead *Node
var newCur *Node
for cur != nil {
nextNode := cur.Next
cur.Next = nextNode.Next
cur = cur.Next
if newCur == nil {
newHead = nextNode
newCur = newHead
continue
}
newCur.Next = nextNode
newCur = newCur.Next
}
return newHead
}

本文介绍了如何复制一个带有random指针的复杂链表,详细解析了使用哈希映射和衍生+拼接两种解题方法,包括难点在于构建新链表中节点的random引用,以及具体的实现步骤和代码展示。
&spm=1001.2101.3001.5002&articleId=122313971&d=1&t=3&u=ba71f2d0be0a4ef4b34a19e312ae7aef)
244

被折叠的 条评论
为什么被折叠?



