首页 > 其他分享 >复制带随机指针的链表

复制带随机指针的链表

时间:2022-10-03 19:00:08浏览次数:80  
标签:cur random next 链表 随机 null 节点 指针

复制带随机指针的链表

作者:Grey

原文地址:

博客园:复制带随机指针的链表

CSDN:复制带随机指针的链表

题目描述
一种特殊的单链表节点类描述如下

class Node {
    int val;
    Node next;
    Node random;

    public Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}

random 指针是单链表节点结构中新增的指针,random 可能指向链表中的任意一个节点,也可能指向 null,

给定一个由 Node 节点类型组成的无环单链表的头节点 head,请实现一个函数完成这个链表的复制,返回复制的新链表的头节点。

注:要求时间复杂度O(N),额外空间复杂度O(1)

OJ见:LeetCode 138. Copy List with Random Pointer

主要思路

假设原始链表如下,其中虚线表示 random 指针

image

由于空间复杂度需要O(1),所以使用辅助数组的方式不可取,只能在链表上进行原地调整

第一步,将当前节点的复制节点连在当前节点的下一个位置上,如上链表,a'a的复制节点,其他节点同理,首先会得到如下链表

image

第二步,复制节点的 random 指针指向当前节点的 random 指针的下一个位置,以a节点为例,a节点的next就是a的复制节点a'a节点的random节点的next就是a'random指针

a.next.random = a.random.next,由于random指针可能为空,所以a.next.random = a.random == null?null:a.random.next,其余节点类似,示例图如下

image

第三步,以上已经完成了链表元素的复制,接下来是分离原链表和复制链表。

image

aa'节点为例,分离的过程就是

a.next = a.next.next;
a'.next = a'.next.next;

特别要注意最后一个节点,因为最后一个节点的next为空,所以,针对最后一个节点dd'来说

d.next = null;
d'.next = null;

最后返回复制链表的头部即可,本例中,返回a'节点即可。

完整代码见

class Solution {
    public static Node copyRandomList(Node head) {
        if (head == null) {
            return null;
        }
        // 以下方法将每个节点的复制节点都在这个节点后面
        // 如果链表是:1->2->3->4 复制以后,会变成: 1->1->2->2->3->3->4->4
        Node cur = head;
        while (cur != null) {
            Node tmp = cur.next;
            Node copy = new Node(cur.val);
            cur.next = copy;
            copy.next = tmp;
            cur = tmp;
        }

        // 以下方法是设置每个复制节点的random指针
        cur = head;
        while (cur != null) {
            cur.next.random = cur.random == null ? null : cur.random.next;
            // 无须判断cur.next是否空指针,因为cur永远是原链表的位置,cur只要不为null
            // cur.next必为复制节点,所以cur只要不为空,cur.next一定存在
            cur = cur.next.next;
        }

        // 以下方法是断开原链表和复制链表,注意最后一个节点
        cur = head;
        Node copyHead = head.next;
        Node copyCur = copyHead;
        Node start = copyHead.next;
        head.next = null;
        int i = 1;
        while (start != null) {
            Node next = start.next;
            if ((i & 1) == 1) {
                cur.next = start;
                cur = start;
            } else {
                copyCur.next = start;
                copyCur = start;
            }
            i++;
            start = next;
        }
        cur.next = null;
        copyCur.next = null;
        return copyHead;
    }
}

本题的所有图例见: processon:复制带随机指针的链表

更多

算法和数据结构笔记

标签:cur,random,next,链表,随机,null,节点,指针
From: https://www.cnblogs.com/greyzeng/p/16750999.html

相关文章

  • LeetCode 75 突破:环形链表 II
    LeetCode75学习计划适用于想为技术面试做准备但不确定应该聚焦于哪些题目的用户。学习计划中的题目都是经过精心挑选的,Level1和Level2学习计划是为初级用户和中级用户......
  • 代码随想录day10 ● 459.重复的子字符串 ● 字符串总结 ● 双指针回顾
    459.重复的子字符串1classSolution{2public:3boolrepeatedSubstringPattern(strings){4stringt=s+s;5//掐头去尾6......
  • C语言入门—明明的随机数
    题目描述明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的......
  • Leetcode 2337 -- 双指针&&脑筋急转弯
    题目描述在LR字符串中交换相邻字符给定我们一个只由\('L','R','X'\)组成的字符串。现在给你两个字符串\(start\)和\(end\),问你能否通过以下两个字符串变换,将字符串......
  • LeetCode142 环形链表
       idea:对于有环结构的链表,判断环结点位置,开始想到遍历链表,直到某一个结点出现第二遍,所以要进行比对的过程,想到前面学到利用哈希表解决相交链表,可以在这使用。不过......
  • 1105 链表合并——25分
    给定两个单链表L1=a1→a2→⋯→an−1→an和L2=b1→b2→⋯→bm−1→bm。如果n≥2m,你的任务是将⽐较短的那个链表逆序,然后将之并⼊⽐较⻓的那个链表,得到⼀个形如a1→a2......
  • 二维随机生长法-原创
    测试案例%demo1%node1=genQSGS2d([100100],0.3,0.01,[0.2,0.1]);%demo2prob=[0.10.10.10.10.20.050.20.05]';node2=genQSGS2d([100100],0.4,0.007,......
  • C++——指针
    一、指针的定义1int*p;2int*p;3int*p;4int*p;首先可以肯定的是上述四种写法(未初始化)都是可以的(本人推荐第一种,不因为什么,看着舒服!!!......
  • readFile 从文件指针指向的位置开始将数据读出到一个文件中
    从文件指针指向的位置开始将数据读出到一个文件中,且支持同步和异步操作,如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话,当程序调用成功时,它将实际读出文件的字节数保存......
  • LeetCode86 分隔链表
     idea:烦死了,这个题一直因为创立的指针为空,或者接入结点方法不对,结果将两个小链表搞混乱了,不过具体思路ok。将小值结点成一组,大值结点成一组,最后在首尾相连,实现起来也比......