力扣138-复制带随机指针的链表

120 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

这个是力扣的题目 138. 复制带随机指针的链表 - 力扣(LeetCode)

思路

我们先拿到链表的第一个节点,然后我们创建一个节点,这个新创建的节点的值复制拿到的节点,然后把新创建的节点放到拿到节点的后面。

然后拿到第一个节点next.next的那个节点,为什么是next.next呢?

因为我们新创建的节点在后面,所以要两个next

按照第一步也复制一个,然后找后面那个。

这个时候我们就有一个新的链表了。

这个时候就需要把随机指针的值复制给新创建的节点。

这个怎么做呢?

我们可以拿到第一个元素,我们知道第二个元素是第一个元素的复制。

我们先找到第一个元素指向的随机元素,然后我们让第二个元素指向第一个元素指向的随机元素的后面那个元素。

以此往复,我们新创建的节点都知道了老节点的随机。

之后我们把他们分离就好了。

代码

节点类代码

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

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

这个是节点类

调用函数

public static Node copyRandomList(Node head){
    if(head == null){
        return null;
    }
    addNew(head);
    copyRandom(head);
    Node newHead = newNode(head);
    return newHead;
}

这个调用函数记得判空

添加新的节点在老节点后面的函数

public static void addNew(Node head){
    Node oldNode = head;
    while(oldNode != null){
        Node newNode = new Node(oldNode.val);
        Node next = oldNode.next;
        oldNode.next = newNode;
        newNode.next = next;
        oldNode = next;
    }
}

这边的注意事项是老节点在后移的是记得是要移动两次的

把老节点的random拷贝

public static void copyRandom(Node head){
    Node oldNode = head;
    while(oldNode != null){
        Node newNode = oldNode.next;
        newNode.random = oldNode.random == null ? null : oldNode.random.next;
        oldNode = oldNode.next.next;
    }
}

这边的注意事项就是拷贝的random节点是老节点的random.next,千万不要忘记next。

分离新老节点

public static Node newNode(Node head){
    Node newHead = head.next;
    Node oldNode = head;
    while(oldNode != null){
        Node newNode = oldNode.next;
        Node next = oldNode.next.next;
        oldNode.next = next;
        newNode.next = next == null ? null : next.next;
        oldNode = next;
    }
    return newHead;
}

这边的注意事项比较多,首先,next的掌控是比较重要的。

newNode.next = next == null ? null : next.next;

这个是要注意一点的,千万不要

newNode.next = next.next;

这样写是会出问题的。