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

我们来详细讲解一下“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

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

阅读剩余 70%

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

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

相关文章

  • HTML5资源预加载(Link prefetch)详细介绍(给你的网页加速)

    HTML5资源预加载(Link prefetch)是一种Web优化技术,可以在页面加载前预先加载页面中需要用到的资源,包括图片、CSS文件、JavaScript文件等,从而提高页面的加载速度和性能。这里将详细介绍HTML5资源预加载的使用方法和注意事项,帮助优化网页加载速度。 HTML5资源预加载介绍 HTML5资源预加载使用<link>标签来指…

    other 2023年6月25日
    00
  • javascript实现验证IP地址等相关信息代码

    当使用JavaScript实现验证IP地址和相关信息的代码时,可以按照以下步骤进行操作: 创建一个函数来验证IP地址的格式。可以使用正则表达式来检查IP地址是否符合标准的IPv4或IPv6格式。下面是一个示例代码: function validateIPAddress(ipAddress) { // 检查IPv4格式 var ipv4Regex = /^(\…

    other 2023年7月31日
    00
  • Java递归简单实现n的阶乘

    当我们需要处理一些类似于树、序列这样递归性质的问题时,递归函数便是一个很好的解决方法。递归函数使用自身调用的方式来解决问题,为我们提供了一种更为简单的解决方案。 下面我们来讲一下Java递归简单实现n的阶乘的完整攻略。 定义递归函数:我们可以使用一个函数来实现n的阶乘的计算,这个函数需要传入一个参数,表示要计算的n的值。函数的定义如下: public sta…

    other 2023年6月27日
    00
  • vue新建项目并配置标准路由过程解析

    下面是Vue新建项目并配置标准路由的完整攻略: 步骤一:安装Vue CLI 安装Vue CLI是使用Vue.js创建新项目的第一步。Vue CLI可以让你快速构建基于Vue.js的应用程序,还可以自动生成标准的项目结构和配置,让开发变得更加高效。运行以下命令安装Vue CLI: npm install -g @vue/cli 步骤二:创建新项目 完成Vue …

    other 2023年6月27日
    00
  • 浅谈一下Spring中的createBean

    浅谈一下Spring中的createBean 在Spring框架中,createBean是一个重要的方法,用于创建和初始化Bean对象。本文将详细讲解createBean的使用方法和示例。 1. createBean方法的作用 createBean方法是Spring框架中的一个核心方法,用于创建和初始化Bean对象。它的主要作用包括: 实例化Bean对象:根…

    other 2023年8月6日
    00
  • C语言数据结构之双向循环链表的实例

    C语言数据结构之双向循环链表的实例 什么是双向循环链表? 双向循环链表是一种链式存储结构。每个节点都包含两个指针域,分别指向前一个节点和后一个节点,形成一个环形结构。双向循环链表可以实现正向和反向遍历,插入和删除节点的时间复杂度为$O(1)$。 双向循环链表的结构体定义 typedef struct Node { ElemType data; struct …

    other 2023年6月27日
    00
  • C++超详细讲解模板的使用

    C++超详细讲解模板的使用攻略 什么是模板 模板是C++中一种基于泛型编程的重要特性,可以让程序员编写可重用的代码模块来处理多种数据类型和算法。模板是由两个部分组成的: 类型参数:表示泛型中的数据类型,通常用T来表示; 模板参数:表示模板中的常量参数,通常用N来表示。 例如: template <typename T, int N> class …

    other 2023年6月27日
    00
  • 用PHP实现递归循环每一个目录

    要用PHP实现递归循环每一个目录,可以遵循以下步骤: 使用PHP中的opendir()函数打开目录,并使用readdir()函数读取目录中的文件和文件夹; 判断读取的目录项是否为文件夹,如果是文件夹,则使用递归的方式进入该文件夹,继续读取其中的文件和文件夹; 如果读取到的是文件,则根据需要进行操作,比如输出文件名等; 在每次调用自身完成递归读取后,需要使用c…

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