题目描述:

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的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.加入copy结点
public void copyNodes(RandomListNode pHead){
RandomListNode walkNode=pHead;
while(walkNode!=null){
RandomListNode cloneNode=new RandomListNode(walkNode.label);
cloneNode.next=walkNode.next;
walkNode.next=cloneNode;
walkNode=cloneNode.next;
}
}

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

//2.为新copy结点的random域指定值
public void initRandom(RandomListNode pHead){
RandomListNode walkNode=pHead;
RandomListNode cwalkNode=pHead;
while(walkNode!=null){
cwalkNode=walkNode.next;
if(walkNode.random!=null){
cwalkNode.random=walkNode.random.next;
}
walkNode=cwalkNode.next;
}
}

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

//3.将链表和其copy版本分为两个链表
public RandomListNode split2list(RandomListNode pHead){
RandomListNode cpHead=pHead.next;
RandomListNode walkNode=pHead;
RandomListNode cwalkNode=cpHead;
while(walkNode!=null){
walkNode.next=cwalkNode.next;
walkNode=walkNode.next;
if(walkNode==null){
cwalkNode.next=null;
}
else{
cwalkNode.next=walkNode.next;
cwalkNode=cwalkNode.next;
}
}
return cpHead;
}

4、总的调用函数

public RandomListNode Clone(RandomListNode pHead)
{
if(pHead==null){
return null;
}
copyNodes(pHead);
initRandom(pHead);
return split2list(pHead);
}

全部代码

 class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
} public class copyList {
//1.加入copy结点
public void copyNodes(RandomListNode pHead){
RandomListNode walkNode=pHead;
while(walkNode!=null){
RandomListNode cloneNode=new RandomListNode(walkNode.label);
cloneNode.next=walkNode.next;
walkNode.next=cloneNode;
walkNode=cloneNode.next;
}
}
//2.为新copy结点的random域指定值
public void initRandom(RandomListNode pHead){
RandomListNode walkNode=pHead;
RandomListNode cwalkNode=pHead;
while(walkNode!=null){
cwalkNode=walkNode.next;
if(walkNode.random!=null){
cwalkNode.random=walkNode.random.next;
}
walkNode=cwalkNode.next;
}
}
//3.将链表和其copy版本分为两个链表
public RandomListNode split2list(RandomListNode pHead){
RandomListNode cpHead=pHead.next;
RandomListNode walkNode=pHead;
RandomListNode cwalkNode=cpHead;
while(walkNode!=null){
walkNode.next=cwalkNode.next;
walkNode=walkNode.next;
if(walkNode==null){
cwalkNode.next=null;
}
else{
cwalkNode.next=walkNode.next;
cwalkNode=cwalkNode.next;
}
}
return cpHead;
}
public RandomListNode Clone(RandomListNode pHead)
{
if(pHead==null){
return null;
}
copyNodes(pHead);
initRandom(pHead);
return split2list(pHead);
}
public static void main(String[]args){
RandomListNode head = new RandomListNode(1);
RandomListNode node2 = new RandomListNode(2);
RandomListNode node3 = new RandomListNode(3);
RandomListNode node4 = new RandomListNode(4);
RandomListNode node5 = new RandomListNode(5);
head.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
head.random = node3;
node2.random = node5;
node4.random = node2;
copyList s = new copyList();
RandomListNode copyList=s.Clone(head);
System.out.print(copyList.label + " ");
// while (copyList != null)
// {
// System.out.print(copyList.label + " ")
// copyList = copyList.next;
// }
}
}

复杂链表的复制——牛客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. git 和conding.net 超详细超简单安装

    在做一下操作前,希望你能知道 1.什么是git? 可以参考https://blog.csdn.net/a909301740/article/details/81636662 如果还想多了解一下还可以参 ...

  2. Linux中touch命令使用(创建文件)

    touch命令有两个功能: 1.用于把已存在文件的时间标签更新为系统当前的时间(默认方式),它们的数据将原封不动地保留下来: 2.用来创建新的空文件. 语法 touch(选项)(参数) 选项 -a:或 ...

  3. leetcode 127. Word Ladder、126. Word Ladder II

    127. Word Ladder 这道题使用bfs来解决,每次将满足要求的变换单词加入队列中. wordSet用来记录当前词典中的单词,做一个单词变换生成一个新单词,都需要判断这个单词是否在词典中,不 ...

  4. Redis发生异常WRONGTYPE Operation against a key holding the wrong kind of value

    Redis发生异常WRONGTYPE Operation against a key holding the wrong kind of value Redis发生异常WRONGTYPE Operat ...

  5. 阶段5 3.微服务项目【学成在线】_day18 用户授权_09-动态查询用户的权限-认证服务查询用户权限

    认证服务查询用户权限 如果权限为空就New一个对象出来. 因为如果为空的话 下面 forEach就会报空指针的异常 启动服务测试 重新登陆 看到userExt已经获取到了用户的权限 权限的字符串 复制 ...

  6. 【425】堆排序方法(二叉堆)优先队列(PQ)

    参考:漫画:什么是二叉堆? 大根堆 小根堆 参考:漫画:什么是堆排序? 参考:漫画:什么是优先队列? 参考:[video]视频--第14周10--第8章排序10--8.4选择排序3--堆排序2--堆调 ...

  7. pytorch0.4.1安装

    pytorch官网:https://pytorch.org/ 这里安装pytorch0.4.1版本(最新版本为1.3.0系列,但是在跑github上的一些项目时会不断地报“ UseWarinig:Le ...

  8. 容器版单个jenkins实现CI/CD----带solo博客开源项目

    实验架构: 192.168.0.96 gitlab 192.168.0.97 jenkins.docker-1.7 192.168.0.98 harbor.docker-1.7集群 jenkins安装 ...

  9. vmware安装密钥

    VMware虚拟机已升级至14版本,之前的12版本的秘钥已经无法使用,在此分享一下VMware Workstation 14永久激活密钥: CG54H-D8D0H-H8DHY-C6X7X-N2KG6 ...

  10. iOS-app清除缓存

    一直寻寻觅觅找app的清除缓存的方法,发现:并没有什么固定的方法,你既然有做对应的缓存机制,这个机制就应该有清除缓存的方法.例如如果你使用某个第三方的图片库,这个库有缓存机制,那么它就应该提供对应的清 ...