【链表】——剑指Offer35复杂链表的复制

161 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

来源:力扣(LeetCode) 链接

思路

这个一道比较经典的题目,主要的难点在于random指针的处理,由于第一个节点的random可能指向后面的节点,而在复制链表的时候后面的节点还没有创建不知道random应该指向哪里,但是也可以用map存储对应的链表中节点和random指向节点的映射,然后对应去copy的链表中去操作,但是这样比较耗费空间,下面来介绍下比较常见的做法

1.在原来的链表上面进行复制,在原来链表的每个节点后面都挂上一个和该节点相同的节点,这样链表的大小就变为原来的2倍

2.对random指针进行指向

3.拆分两个链表

代码

public Node copyRandomList(Node head) {
    if (head == null) return null;  //如果head为空直接返回
    Node temp = head;              //辅助指针temp
    while (temp != null) {         //第一步:先对链表进行复制,就是在每个节点后面都复制一个相同的节点
        Node next = temp.next;      //记录next节点的位置
        temp.next = new Node(temp.val); //复制节点
        temp.next.next = next;          //复制节点的next指向next节点
        temp = next;                    //移动指针到next节点
    }
    temp = head;
    while (temp != null) {               //第二步:对random进行操作
        temp.next.random = temp.random == null ? null : temp.random.next;
        if (temp.next.next == null) break;  //这边判断一下跳出,不然会出现空指针异常
        temp = temp.next.next;             //指针向下一个节点移动
    }
    //第三步:  开始拆分

    temp = head;
    Node temp1 = head.next;
    Node head1 = temp1;    //记录复制的链表的头节点的位置
    while (temp != null) {
        temp.next = temp.next.next;  //断开链表,
        if (temp.next == null) break;
        temp1.next = temp.next.next;
        temp = temp.next;
        temp1 = temp1.next;
    }
    return head1;

}