Java面试题-实现复杂链表的复制代码分享

yizhihongxing

我们来详细讲解一下“Java面试题-实现复杂链表的复制代码分享”的完整攻略。

确定复制思路

在复制带有随机指针的链表时,我们需要对每个节点都进行深拷贝,并且需要关联原链表中同样的随机指针,因此需要考虑以下几个步骤:

  1. 添加新的节点
  2. 复制原链表中的节点
  3. 连接新旧链表
  4. 复制随机指针

添加新的节点

首先,我们需要对原始链表中的每个节点进行拷贝,并且将拷贝后的节点插入在原始节点的后面。这里我们可以使用链表的插入方法,将新的节点插入到原始节点的后面,具体实现如下:

public static void cloneNodes(ComplexListNode head) {
    ComplexListNode node = head;
    while (node != null) {
        ComplexListNode cloned = new ComplexListNode(node.val);
        cloned.next = node.next;
        cloned.random = null;
        node.next = cloned;
        node = cloned.next;
    }
}

这里我们新创建了一个cloned节点,并且将其插入在node.next的位置上,之后我们更新node节点的指向,指向cloned节点的下一个节点,这样子便完成了新的节点的插入。

复制原链表中的节点

在第一步完成后,我们已经实现了对新链表节点的创建,接下来需要将原始链表中的节点复制到新链表中。对于每一个原始链表中存在的节点,我们可以通过链表的遍历,通过node.next获取到其对应的新链表中的节点,并且为新链表中对应的节点设置随机指针指向,具体实现如下:

public static void connectSiblingNodes(ComplexListNode head) {
    ComplexListNode node = head;
    while (node != null) {
        ComplexListNode cloned = node.next;
        if (node.random != null) {
            cloned.random = node.random.next;
        }
        node = cloned.next;
    }
}

这里,我们首先复制了head节点,并将其赋值给node,接下来我们进行遍历,每次取出原始节点的下一个节点,并且将其赋值给cloned节点。如果原始节点存在random指针,那么我们需要将其指向的节点在新链表中的节点赋值给clonedrandom指针。

连接新旧链表

完成前两个步骤后,我们已经创建了与原始链表对应位置的新链表,并且为其连接了随机指针指向。接下来,我们需要将两个链表分开,并且返回只包含新链表的头结点。具体实现如下:

public static ComplexListNode reconnectNodes(ComplexListNode head) {
    ComplexListNode node = head;
    ComplexListNode clonedHead = null;
    ComplexListNode clonedNode = null;
    if (node != null) {
        clonedHead = clonedNode = node.next;
        node.next = clonedNode.next;
        node = node.next;
    }
    while (node != null) {
        clonedNode.next = node.next;
        clonedNode = clonedNode.next;
        node.next = clonedNode.next;
        node = node.next;
    }
    return clonedHead;
}

这里,我们首先取出原始链表中的第一个节点,并且根据第一步中新创建的节点,取出对应位置的新链表中的头结点,并将其赋值给clonedHeadclonedNode。接下来进行遍历,分别移动新旧链表中的指针,并将其连接起来。最后返回只包含新链表的头结点。

完整代码

将以上三步整合起来,我们得到完整的复制带随机指针链表的代码实现:

class ComplexListNode{
    int val;
    ComplexListNode next;
    ComplexListNode random;
    public ComplexListNode(int val) {
        this.val = val;
    }
}

public static ComplexListNode clone(ComplexListNode head) {
    cloneNodes(head);
    connectSiblingNodes(head);
    return reconnectNodes(head);
}

public static void cloneNodes(ComplexListNode head) {
    ComplexListNode node = head;
    while (node != null) {
        ComplexListNode cloned = new ComplexListNode(node.val);
        cloned.next = node.next;
        cloned.random = null;
        node.next = cloned;
        node = cloned.next;
    }
}

public static void connectSiblingNodes(ComplexListNode head) {
    ComplexListNode node = head;
    while (node != null) {
        ComplexListNode cloned = node.next;
        if (node.random != null) {
            cloned.random = node.random.next;
        }
        node = cloned.next;
    }
}

public static ComplexListNode reconnectNodes(ComplexListNode head) {
    ComplexListNode node = head;
    ComplexListNode clonedHead = null;
    ComplexListNode clonedNode = null;
    if (node != null) {
        clonedHead = clonedNode = node.next;
        node.next = clonedNode.next;
        node = node.next;
    }
    while (node != null) {
        clonedNode.next = node.next;
        clonedNode = clonedNode.next;
        node.next = clonedNode.next;
        node = node.next;
    }
    return clonedHead;
}

示例说明

假设我们有一个链表为:

1 -> 2 -> 3 -> null
|    |
V    V
2 -> 3

我们可以根据以上代码实现将其深拷贝,得到新的链表:

1 -> 2 -> 3 -> null
|    |
V    V
2 -> 3

其中新链表中的每个节点都与原始链表中对应,而且随机指针指向也正确。这里为了方便演示,我们只展示了一个示例。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java面试题-实现复杂链表的复制代码分享 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 关于自动化测试框架pytest的Fixture固件

    关于自动化测试框架pytest的Fixture固件攻略 什么是Fixture固件? 在pytest中,Fixture固件是一种用于提供测试环境的机制。它可以在测试用例执行之前或之后执行一些预定义的操作,例如创建、初始化或清理测试数据、启动或关闭服务等。Fixture固件可以帮助我们更方便地编写和管理测试用例。 如何使用Fixture固件? 1. 定义Fixt…

    other 2023年8月21日
    00
  • OPPO手机存储空间不足怎么办?OPPO手机清理内存方法

    OPPO手机存储空间不足怎么办? 如果你的OPPO手机存储空间不足,可以采取以下方法来清理内存和释放空间。 1. 清理应用缓存和数据 应用缓存和数据占据了大量的存储空间,清理它们可以释放一些空间。你可以按照以下步骤进行操作: 打开手机的设置菜单。 滑动到\”应用管理\”或\”应用和通知\”选项。 选择要清理的应用。 点击\”存储\”或\”存储空间\”选项。 …

    other 2023年8月1日
    00
  • 微软工具ilmerge

    微软工具ilmerge ilmerge是由微软提供的一个命令行工具,可以把多个.NET程序集合并成一个程序集。 安装和使用 ilmerge可以从NuGet中获取,也可以从官方网站下载。 安装好ilmerge后,打开命令行工具,切换到包含程序集文件的目录中,使用以下命令即可将多个程序集合并成一个程序集: ilmerge /out:Merged.dll Asse…

    其他 2023年3月29日
    00
  • php变量作用域的深入解析

    PHP变量作用域的深入解析 在PHP中,变量的作用域指的是变量在程序中可访问的范围。了解PHP变量作用域的概念对于编写可维护和可扩展的代码非常重要。本攻略将详细讲解PHP变量作用域的各种情况和规则。 全局作用域 全局作用域是指在整个脚本中都可访问的变量。在PHP中,任何在函数外部定义的变量都具有全局作用域。全局作用域的变量可以在脚本的任何地方访问。 示例1:…

    other 2023年7月29日
    00
  • 去掉鼠标右键菜单里面的”用阿里旺旺发送此文件…”

    下面就是去掉鼠标右键菜单里面的”用阿里旺旺发送此文件…” 的完整攻略: 第一步:打开注册表 在 Windows 操作系统中,右键菜单是通过注册表控制的。因此,我们第一步需要打开注册表,具体步骤如下: 按下 “Win + R” 组合键打开 “运行” 窗口; 输入 “regedit” 并按下 “Enter” 键打开注册表编辑器。 第二步:定位到相关的注册表键…

    other 2023年6月27日
    00
  • Java利用Reflect实现封装Excel导出工具类

    下面我来详细为你讲解“Java利用Reflect实现封装Excel导出工具类”的完整攻略。 什么是Reflect(反射)? Java中的反射机制是指在运行时动态地获取类的信息和调用类的方法的机制。通过反射机制可以实现访问对象的属性和方法,这种机制使得Java具有非常大的灵活性和可扩展性。 需求说明 最近有一个需求是从Java程序中导出数据到Excel表格,需…

    other 2023年6月25日
    00
  • Android实现简单底部导航栏 Android仿微信滑动切换效果

    Android实现简单底部导航栏 在Android应用中,底部导航栏是一种常见的UI组件,用于在不同的页面之间进行导航。本攻略将详细介绍如何实现一个简单的底部导航栏,并提供两个示例说明。 步骤一:准备工作 在Android Studio中创建一个新的项目。 在项目的布局文件中添加一个底部导航栏的容器,例如使用LinearLayout或RelativeLayo…

    other 2023年8月26日
    00
  • 网卡MAC地址是什么?如何修改网卡MAC地址

    网卡MAC地址是什么? 网卡MAC地址(Media Access Control address)是一个唯一的标识符,用于识别网络设备(如计算机、手机、路由器等)在局域网中的身份。MAC地址由48位二进制数表示,通常以十六进制的形式显示。 MAC地址由两部分组成:前24位是厂商识别码(OUI,Organizationally Unique Identifie…

    other 2023年7月30日
    00
合作推广
合作推广
分享本页
返回顶部