题目:请实现一个函数,复制一个复杂链表。

在复杂链表中,每个结点除了有一个next指针指向下一个结点外,还有一个sibling指针指向链表中的任意结点或者nulL

直观解法:

1.遍历链表,复制链表节点,并连接next节点。2.遍历链表,连接sibling节点。对于一个有n个节点的链表,由于定位每个节点的silbing节点都需要从链表的头结点开始经过O(n)步才能实现,因此这种方法的时间复杂度是O(n2)

优化解法:上述方法的时间主要是用在了sibling节点的定位上,考虑优化此步骤。具体的做法是在复制节点的时候,把原节点N和复制出来的N'节点用一个map保存起来,这样在第二部连接sibling结点的时候就可以以O(1)的时间复杂度定位到相应的sibling节点,总体时间复杂度为O(n),空间复杂度也是O(n)

最优算法:

第一步:根据原始链表的每个节点创建对应的复制结点,把复制结点连接在原结点的后面
第二步:设置复制出来的结点的任意结点sibling节点
第三步:把长链表拆分成两个链表

 package Solution;

 public class No26CopyComplexList {

     static class ComplexListNode{
int value;
ComplexListNode next;
ComplexListNode sibling;
public ComplexListNode(){ }
public ComplexListNode(int value,ComplexListNode next,ComplexListNode sibling){
this.value=value;
this.next=next;
this.sibling=sibling;
}
} //把复杂链表中的所有结点进行复制,并连接在原结点的后面
private static void cloneNode(ComplexListNode head){
ComplexListNode node=head;
while(node!=null){
ComplexListNode clonedNode=new ComplexListNode();
clonedNode.value=node.value;
clonedNode.next=node.next;
clonedNode.sibling=null;
node.next=clonedNode;
node=clonedNode.next;
}
}
//设置复制的节点的指向任意结点的连接关系
private static void connectSiblingNodes(ComplexListNode head){
ComplexListNode node=head;
while(node!=null){
ComplexListNode clonedNode=node.next;
if(node.sibling!=null){
clonedNode.sibling=node.sibling.next;
}
node=clonedNode.next;
}
}
//把长链表拆分成两个单独的链表,并返回复制后的链表的头结点
private 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=clonedNode.next;
}
while(node!=null){
clonedNode.next=node.next;
clonedNode=node.next;
node.next=clonedNode.next;
node=clonedNode.next;
}
return clonedHead;
}
public static ComplexListNode copyComplexList(ComplexListNode head){
if(head==null)
return null;
cloneNode(head);
connectSiblingNodes(head);
return reconnectNodes(head);
} public static void printComplexList(ComplexListNode head){
ComplexListNode node=head;
int value=0;
ComplexListNode next=null;
ComplexListNode sibling=null;
while(node!=null){
value=node.value;
next=node.next;
sibling=node.sibling;
StringBuilder sb=new StringBuilder("当前节点的值为:").append(value);
if(next!=null)
sb.append(",下一结点的值为:").append(next.value);
else
sb.append(",当前结点为尾节点");
if(sibling!=null)
sb.append(",指向任意结点的值为:").append(sibling.value);
else
sb.append(",没有指向其他结点的任意结点");
System.out.println(sb.toString());
node=node.next;
}
}
public static void main(String[] args) {
ComplexListNode node1=new ComplexListNode();
ComplexListNode node2=new ComplexListNode();
ComplexListNode node3=new ComplexListNode();
ComplexListNode node4=new ComplexListNode();
ComplexListNode node5=new ComplexListNode();
node1.value=1;
node1.next=node2;
node1.sibling=node3;
node2.value=2;
node2.next=node3;
node2.sibling=node5;
node3.value=3;
node3.next=node4;
node3.sibling=null;
node4.value=4;
node4.next=node5;
node4.sibling=node2;
node5.value=5;
node5.next=null;
node5.sibling=null;
printComplexList(node1);
System.out.println("=========================开始复制============================");
printComplexList(copyComplexList(node1));
}
}

剑指offer面试题26:复杂链表的复制的更多相关文章

  1. 剑指offer 面试题35.复杂链表的复制

    时间O(N),空间O(N) /* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomList ...

  2. 剑指offer面试题26-复杂链表的复制

    题目: 请实现函数ComplexListNode* Clone(ComplexListNode* pHead).复制一个复杂链表. 在复杂链表中.每个节点除了一个m_pNext指针指向下一个节点外,另 ...

  3. 剑指Offer - 九度1524 - 复杂链表的复制

    剑指Offer - 九度1524 - 复杂链表的复制2014-02-07 01:30 题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点 ...

  4. 剑指Offer面试题:14.链表的倒数第k个节点

    PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善. 一.题目:链表的倒数第k个节点 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题 ...

  5. 剑指Offer:面试题26——复制复杂的链表(java实现)

    问题描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 思路1: 1.先复制链表节点,并用next链接起来. 2.然后对每一个结点去修改 ...

  6. 剑指Offer:面试题16——反转链表(java实现)

    问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = n ...

  7. 【剑指offer 面试题15】链表中倒数第K个结点

    思路: 定义两个指针同时指向head,第一个指针先走K-1步,随后二个指针同时移动,当第一个指针到末尾处时,第二个指针所指向的即为倒数第K个结点. #include <iostream> ...

  8. 剑指offer面试题15:链表中倒数第K个节点

    题目:输入一个链表,输出该链表的倒数第K个节点.为了符合大多数人的习惯,本题从1开始计数,即链表尾节点是倒数第一个节点. 解题思路: 解法一:一般情况下,单向链表无法从后一个节点获取到它前面的节点,可 ...

  9. 剑指offer——面试题23:链表中环的入口节点

    函数: ListNode* MeetingNode(ListNode* pHead) { if(pHead==nullptr) return nullptr; ListNode* quickNode= ...

随机推荐

  1. CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-6CM安装前环境检查

    检查环境 在正式开始安装CDH之前最好先检查一下能不能相互免密ssh,以及防火墙是否关闭,集群中的时间是否统一,java版本是否是oracle的版本,主节点mysql是否安装正确等. ssh测试 例如 ...

  2. gridview 选中某行后 某行的按钮显示,无选中则隐藏

    如后面的加号,选中行时出现,未被选中的隐藏 解决: 在按钮中的visibility属性中绑定该item是否选中,再用转换器转换 <Button Name="btnA" Cli ...

  3. 用7ch中断例程完成jmp near ptr s指令的功能,用bx向中断例程传送转移位移。

    应用举例:在屏幕的第12行,显示data段中以0结尾的字符串. assume cs:code data segment db data ends code segment start: mov ax, ...

  4. 20164319 刘蕴哲 Exp5 MSF基础应用

    [实践内容] 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.1一个主动攻击实践(这里我做了两个:ms08_067[成功]和ms17_010[成功 ...

  5. Python 的 14 张思维导图汇总

    本文主要涵盖了 Python 编程的核心知识(暂不包括标准库及第三方库,后续会发布相应专题的文章). 首先,按顺序依次展示了以下内容的一系列思维导图:基础知识,数据类型(数字,字符串,列表,元组,字典 ...

  6. bootstrap-table 踩坑手记

    官方文档: http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/ 渲染表格有两种方法: 1)data属性渲染表格 2)js代码渲染表 ...

  7. centos/RHEL 7.6 使用yum安装php7.3(方便wordpress的php7.3需求,并解决了libphp7.so缺失问题)

    我最近想安装一个wordpress, 但是官网介绍需要php7.3以上版本,但是百度了一下,都是要编译安装. 为此,我想,centos..., php... 两大当红辣子鸡没有yum安装方式,简直不可 ...

  8. Flask cookie

    一 什么是cookie        什么是cookie?如果单单从数据结构的角度来说,它可以被理解成用来保存数据的一个dictionary,由一组组键值对组成.如果从作用上来说,我们知道Http协议 ...

  9. asp.net core部署到iis中出现 HTTP Error 502.5 - Process Failure的问题

    环境是windows Server2012  问题的原因是缺少文件:api-ms-win-crt-runtimel1-1-0.dll, dotnet 启动程序失败. 解决方案1: 安装系统补丁: 20 ...

  10. java38

    字符串内存分析 String str = new String("ABCD") 会先在堆中开辟一个空间,然后去常量池(方法区)中寻找是否有该变量,如果有,直接引用常量池中的内容 如 ...