【LeetCode】剑指 Offer 35. 复杂链表的复制 - Go 语言题解


一、题目描述

请实现 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 = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。

提示:

  • -10000 <= Node.val <= 10000
  • Node.random 为空(null)或指向链表中的节点。
  • 节点数目不超过 1000 。

二、题目理解、解题思路

所谓复制一个链表,就是重新开辟一篇存储空间,在这片存储空间上,重新创建一个新链表,与原链表有同样的值和链接关系。其实就是 链表的深拷贝。想深入理解 golang 深浅拷贝的同学请移步:【Go】深拷贝与浅拷贝

其中,有同样的值很简单(Val 域),有同样的顺序关系也简单(Next 域)。

这个题的难点是实现新链表的 Random 域的正确指向。

要攻克这个难点,我的方法分为四步:

  1. 首先,按照顺序,存储旧链表所有节点的 Random 字段(结构体指针数组 randomlist)。
  2. 在遍历旧链表节点的同时遍历 randomlist,将 randomlist 里存储的地址和当前链表节点的地址做对比,将 randomlist 里存储的地址转化为当前链表节点的序号,存入一个整型数组 index 。这个整型数组存储了每个节点的 Random 域指向了哪一个节点。
  3. 在创建新链表时,将每个节点的地址存入 new_randomlist 。
  4. 遍历新链,根据 index 存储的旧链每个节点的 Random 指向哪个节点的信息,以及 new_randomlist 记录的新链每个节点的地址信息,给新链的每个节点的 Random 域赋值。

三、我的题解

Go 语言代码:

/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Next *Node
 *     Random *Node
 * }
 */

func copyRandomList(Once *Node) *Node {
    if Once == nil{
        return nil
    }
    
    
    var randomlist []*Node     //记录原链表的所有Random字段
    var new_randomlist []*Node //记录新链的所有节点的地址
    
    
    //遍历链表,计算其长度k,并按顺序记录所有Random字段
    rancurr := Once
    k := 0
    for rancurr != nil{
        k ++
        randomlist = append(randomlist,rancurr.Random)
        rancurr = rancurr.Next
    }
    
    index := make([]int, k)     //记录k个节点的Random字段分别指向第几个节点


    var copy_newnode *Node

    //虚拟头结点
    copy_newnode = new(Node)
    head := copy_newnode
    curr := copy_newnode
    
    //创建新链表,并记录每个节点的Random字段分别指向第几个节点
    i := 0   //Once 的第几个节点
    for Once != nil{
        //寻找指向当前节点的其他节点,将其他节点的 index 项更改为当前节点的序号
        for j,d := range randomlist{
            if d == nil{
                index[j] = k
            }else if d == Once {
                index[j] = i
            }
        }
        
        //创建新节点
        copy_newnode = new(Node)
        copy_newnode.Val = Once.Val

        //将新节点的地址加入new_randomlist
        new_randomlist = append(new_randomlist,copy_newnode)
        
        curr.Next = copy_newnode
        curr = curr.Next

        Once = Once.Next
        i++
    }

    //遍历新链,根据 index 的记录和 new_randomlist 里的地址信息给新链所有节点的 Random 域赋值
    curr = head.Next
    for in := 0; in <(len(index)); in++{
        if index[in] == k{
            curr.Random = nil
        }else{
            curr.Random = new_randomlist[index[in]]
        } 
        curr = curr.Next
    }
   

    return head.Next

}

评判结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值