题目描述:

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

数据结构:

public class RandomListNode {
    int label;                                             数据域
    RandomListNode next = null;            指向下一个结点
    RandomListNode random = null;       指向任意一个节点

RandomListNode(int label) {
        this.label = label;
    }
}

解题思路:

1、遍历链表,复制链表中的每个结点,并将复制的结点插入到该结点的后面。例如,原链表为A->B->C, 遍历完毕后,链表变为A->A'->B->B'->C->C',其中A‘,B',C'是结点A,B,C的复制结点。

看图中,蓝色箭头为next指针:

复制结点后:

2、为复制结点的random指针赋值

如果原结点的random指针指向的是结点B,那么将复制结点的random指针指向结点B的复制结点B'。

图中黑色箭头为random指针:

复制结点的random指针赋值后:

3、将链表的原始结点与复制结点分割至两个链表,使原始结点构成一个链表,复制结点构成一个链表。

代码实现:

1、复制结点

  1. //1.加入copy结点
  2. public void copyNodes(RandomListNode pHead){
  3. RandomListNode walkNode=pHead;
  4. while(walkNode!=null){
  5. RandomListNode cloneNode=new RandomListNode(walkNode.label);
  6. cloneNode.next=walkNode.next;
  7. walkNode.next=cloneNode;
  8. walkNode=cloneNode.next;
  9. }
  10. }

2、为复制结点的random指针域赋值

  1. //2.为新copy结点的random域指定值
  2. public void initRandom(RandomListNode pHead){
  3. RandomListNode walkNode=pHead;
  4. RandomListNode cwalkNode=pHead;
  5. while(walkNode!=null){
  6. cwalkNode=walkNode.next;
  7. if(walkNode.random!=null){
  8. cwalkNode.random=walkNode.random.next;
  9. }
  10. walkNode=cwalkNode.next;
  11. }
  12. }

3、将结点和复制结点分为两个链表

  1. //3.将链表和其copy版本分为两个链表
  2. public RandomListNode split2list(RandomListNode pHead){
  3. RandomListNode cpHead=pHead.next;
  4. RandomListNode walkNode=pHead;
  5. RandomListNode cwalkNode=cpHead;
  6. while(walkNode!=null){
  7. walkNode.next=cwalkNode.next;
  8. walkNode=walkNode.next;
  9. if(walkNode==null){
  10. cwalkNode.next=null;
  11. }
  12. else{
  13. cwalkNode.next=walkNode.next;
  14. cwalkNode=cwalkNode.next;
  15. }
  16. }
  17. return cpHead;
  18. }

4、总的调用函数

  1. public RandomListNode Clone(RandomListNode pHead)
  2. {
  3. if(pHead==null){
  4. return null;
  5. }
  6. copyNodes(pHead);
  7. initRandom(pHead);
  8. return split2list(pHead);
  9. }

全部代码

  1. class RandomListNode {
  2. int label;
  3. RandomListNode next = null;
  4. RandomListNode random = null;
  5. RandomListNode(int label) {
  6. this.label = label;
  7. }
  8. }
  9.  
  10. public class copyList {
  11. //1.加入copy结点
  12. public void copyNodes(RandomListNode pHead){
  13. RandomListNode walkNode=pHead;
  14. while(walkNode!=null){
  15. RandomListNode cloneNode=new RandomListNode(walkNode.label);
  16. cloneNode.next=walkNode.next;
  17. walkNode.next=cloneNode;
  18. walkNode=cloneNode.next;
  19. }
  20. }
  21. //2.为新copy结点的random域指定值
  22. public void initRandom(RandomListNode pHead){
  23. RandomListNode walkNode=pHead;
  24. RandomListNode cwalkNode=pHead;
  25. while(walkNode!=null){
  26. cwalkNode=walkNode.next;
  27. if(walkNode.random!=null){
  28. cwalkNode.random=walkNode.random.next;
  29. }
  30. walkNode=cwalkNode.next;
  31. }
  32. }
  33. //3.将链表和其copy版本分为两个链表
  34. public RandomListNode split2list(RandomListNode pHead){
  35. RandomListNode cpHead=pHead.next;
  36. RandomListNode walkNode=pHead;
  37. RandomListNode cwalkNode=cpHead;
  38. while(walkNode!=null){
  39. walkNode.next=cwalkNode.next;
  40. walkNode=walkNode.next;
  41. if(walkNode==null){
  42. cwalkNode.next=null;
  43. }
  44. else{
  45. cwalkNode.next=walkNode.next;
  46. cwalkNode=cwalkNode.next;
  47. }
  48. }
  49. return cpHead;
  50. }
  51. public RandomListNode Clone(RandomListNode pHead)
  52. {
  53. if(pHead==null){
  54. return null;
  55. }
  56. copyNodes(pHead);
  57. initRandom(pHead);
  58. return split2list(pHead);
  59. }
  60. public static void main(String[]args){
  61. RandomListNode head = new RandomListNode(1);
  62. RandomListNode node2 = new RandomListNode(2);
  63. RandomListNode node3 = new RandomListNode(3);
  64. RandomListNode node4 = new RandomListNode(4);
  65. RandomListNode node5 = new RandomListNode(5);
  66. head.next = node2;
  67. node2.next = node3;
  68. node3.next = node4;
  69. node4.next = node5;
  70. head.random = node3;
  71. node2.random = node5;
  72. node4.random = node2;
  73. copyList s = new copyList();
  74. RandomListNode copyList=s.Clone(head);
  75. System.out.print(copyList.label + " ");
  76. // while (copyList != null)
  77. // {
  78. // System.out.print(copyList.label + " ")
  79. // copyList = copyList.next;
  80. // }
  81. }
  82. }

复杂链表的复制——牛客offer的更多相关文章

  1. 合并两个排序链表——牛客offer

    题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解题思路: 1.一般看到合并这类的题目就会很自然的想到创建一个新的链表,然后将两个链表根据一定 ...

  2. 两个链表的第一个公共结点——牛客offer

    题目描述: 输入两个链表,找出它们的第一个公共结点. 题目分析: 只是数据域相同不是公共节点.公共结点代表该节点在两个链表中的数据域和指针域都是相同的,这意味着从该公共节点开始,后面的结点都是两个链表 ...

  3. 链表中环的入口结点 牛客网 剑指Offer

    链表中环的入口结点 牛客网 剑指Offer 题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. # class ListNode: # def __init__(se ...

  4. 链表中倒数第K个结点 牛客网 剑指Offer

    链表中倒数第K个结点 牛客网 剑指Offer 题目描述 输入一个链表,输出该链表中倒数第k个结点. # class ListNode: # def __init__(self, x): # self. ...

  5. 《剑指offer》链表专题 (牛客10.23)

    难度 题目 知识点 03. 返回链表的反序 vector 递归,C++ STL reverse() * 14. 链表中倒数第k个结点 指针操作 15. 反转链表 头插法,递归 16. 合并两个有序链表 ...

  6. 牛客网剑指offer java 全部题解

    经过数月的努力,终于更完了牛客网的66道剑指offer,以下的顺序和大家在牛客网的顺序是一样的(排序也花了不少时间),希望对大家找工作/提高算法能力能起到些许帮助. 每天一道剑指offer-二维数组中 ...

  7. 牛客网剑指offer刷题总结

    二维数组中的查找: 题目描述:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 两 ...

  8. 剑指Offer(二十五):复杂链表的复制

    剑指Offer(二十五):复杂链表的复制 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/bai ...

  9. 【Offer】[35] 【复杂链表的复制】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的he ...

随机推荐

  1. HTTP的POST提交的四种常见消息主体格式

    HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PUT.DELETE.TRACE.CONNECT 这几种.其中 POST 一般用来向服务端提交数据,本文 ...

  2. VUE判断可用对象是否为空

    方法一: JSON.stringify(formmanage_listVue.updataObj)=='{}' var data = {}; var b = (JSON.stringify(data) ...

  3. MongoDB基础笔记

    MongoDB show dbs 查看当前的数据库 use test 选库 show tables/collections 查看当前库下的文档 db.help() 查看帮助 db.createColl ...

  4. python使用redis实现协同控制的分布式锁

    python使用redis实现协同控制的分布式锁 上午的时候,有个腾讯的朋友问我,关于用zookeeper分布式锁的设计,他的需求其实很简单,就是节点之间的协同合作. 我以前用redis写过一个网络锁 ...

  5. oracle库两个表关联查询时用 count 报错【我】

    oracle数据库,需要对两个表进行关联查询(根据两个字段),结果发现关联后不能改为 count 获取数量,报错如下: 同样的sql换到另外一个数据库就可以(只是因为数据量在千万级,所以很慢,用时40 ...

  6. SpringCloud学习成长之路 五 路由器网关

    在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: ...

  7. Spring Boot中mybatis insert 如何获得自增id

    https://www.cnblogs.com/quan-coder/p/8728410.html 注意要显式设置主键,通过: @Options(useGeneratedKeys = true, ke ...

  8. Hadoop概念学习系列之Hadoop、Spark学习路线

    1 Java基础: 视频方面:          推荐<毕向东JAVA基础视频教程>.学习hadoop不需要过度的深入,java学习到javase,在Java虚拟机的内存管理.以及多线程. ...

  9. Egret入门学习日记 --- 第八篇(书中 2.0~2.6节 内容)

    第八篇(书中 2.0~2.6节 内容) 好!开始把前三章的内容录入进来. 但是!由于第一章说的内容都是在介绍白鹭引擎的背景信息,我就不在日记中写了. 直接开始从第二章写起. 2.0节 中提到了IDE( ...

  10. (CVE-2016-5195)脏牛本地提权

    简要分析 该漏洞具体为,get_user_page内核函数在处理Copy-on-Write(以下使用COW表示)的过程中,可能产出竞态条件造成COW过程被破坏, 导致出现写数据到进程地址空间内只读内存 ...