题目概述
- 算法说明
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空) - 测试用例
输入:
{1,2,3,4,5,3,5,#,2,#}
{1,2,3,4,5,#,5,3,2,#}
{1,2,3,4,5,#,4,#,2,#}
{1,#}
{}
输出:
{1,2,3,4,5,3,5,#,2,#}
{1,2,3,4,5,#,5,3,2,#}
{1,2,3,4,5,#,4,#,2,#}
{1,#}
{}
解析&参考答案
- 解析
- 方法1:原始节点后追加法
- 复制链表节点,使原链表1-2-3变为1-1’-2-2’-3-3’
- 复制random 指针,需要考虑random 为nil的情况
- 分离出拷贝的节点,提取出1’-2’-3’
- 方法2:哈希表
- 在map中存储m[原始节点]=拷贝节点
- 将拷贝节点构成一个链表
- 方法1:原始节点后追加法
- 参考答案
vim jz25.go
package main
import "fmt"
type RandomListNode struct {
Label int
Next *RandomListNode
Random *RandomListNode
}
func PrintList(head *RandomListNode) {
if head == nil {
fmt.Print("nil")
} else {
p := head
for p != nil {
if p.Next != nil {
fmt.Printf("%d->", p.Label)
} else {
fmt.Printf("%d\n", p.Label)
}
p = p.Next
}
}
}
func Clone(head *RandomListNode) *RandomListNode {
if head == nil {
return head
}
p := head
// step1: 复制每个节点,并将其插入到该节点之后
for p != nil {
tmp := &RandomListNode{p.Label, p.Next, nil}
p.Next = tmp
p = tmp.Next
}
//PrintList(head)
// step2: 为step1 中每个节点设置 Random指向(其上 一个节点的 Random 的Next节点),此处需要判断p和p.random是否为nil
p = head
for p != nil {
if p.Random != nil {
p.Next.Random = p.Random.Next
}
p = p.Next.Next
}
// step3: 取出偶数节点,该节点就是目标节点
p = head
headNew := head.Next
for p != nil {
cloneNode := p.Next
p.Next = cloneNode.Next
if cloneNode.Next != nil {
cloneNode.Next = cloneNode.Next.Next
}
p = p.Next
}
return headNew
}
func CloneV2(head *RandomListNode) *RandomListNode {
// 使用map 在牛客的oj 上提示超时,有看出错误原因的读者可以帮忙优化下
if head == nil {
return head
}
m := make(map[*RandomListNode]*RandomListNode)
p := head
for p != nil {
m[p] = &RandomListNode{p.Label, nil, nil}
p = p.Next
}
p = head
for p != nil {
if p.Next == nil {
m[p].Next = nil
} else {
m[p].Next = m[p.Next]
}
if p.Random == nil {
m[p].Random = nil
} else {
m[p].Random = m[p.Random]
}
}
return m[head]
}
func main() {
p0 := &RandomListNode{0, nil, nil}
p1 := &RandomListNode{1, nil, nil}
p2 := &RandomListNode{2, nil, nil}
p3 := &RandomListNode{3, nil, nil}
p4 := &RandomListNode{4, nil, nil}
p0.Next, p0.Random = p1, p2
p1.Next, p1.Random = p2, p4
p2.Next, p2.Random = p3, p3
p3.Next, p3.Random = p4, p1
p4.Next, p4.Random = nil, nil
PrintList(p0)
head := Clone(p0)
PrintList(head)
}
注意事项
- to add
说明
- 当前使用 go1.15.8
- 参考 牛客网--剑指offer
标题中jzn(n为具体数字)代表牛客网剑指offer系列第n号题目,例如 jz01 代表牛客网剑指offer中01号题目。
注意!!!
- 笔者最近在学习 golang,因此趁机通过数据结构和算法来进一步熟悉下go语言
- 当前算法主要来源于剑指 offer,后续会进一步补充 LeetCode 上重要算法,以及一些经典算法
- 此处答案仅为参考,不一定是最优解,欢迎感兴趣的读者在评论区提供更优解