#138. Copy List with Random Pointer

Description

A linked list of length n is given such that each node contains an additional random pointer, which could point to any node in the list, or null.

Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, where each new node has its value set to the value of its corresponding original node. Both the next and random pointer of the new nodes should point to new nodes in the copied list such that the pointers in the original list and copied list represent the same list state. None of the pointers in the new list should point to nodes in the original list.

For example, if there are two nodes X and Y in the original list, where X.random --> Y, then for the corresponding two nodes x and y in the copied list, x.random --> y.

Return the head of the copied linked list.

The linked list is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where:

  • val: an integer representing Node.val
  • random_index: the index of the node (range from 0 to n-1) that the random pointer points to, or null if it does not point to any node.

Your code will only be given the head of the original linked list.

Examples

Example 1:
在这里插入图片描述

Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]

Example 2:
在这里插入图片描述

Input: head = [[1,1],[2,1]]
Output: [[1,1],[2,1]]

Example 3:
在这里插入图片描述

Input: head = [[3,null],[3,0],[3,null]]
Output: [[3,null],[3,0],[3,null]]

Example 4:

Input: head = []
Output: []
Explanation: The given linked list is empty (null pointer), so return null.

思路

这个和图其实不太一样,他更多的是链表,random只是一个彩头
按照链表的顺序不停复制next之后,再从头对random进行处理即可

需要注意的是他的value是可能重复的,所以要通过copy前的node作为索引判断具体对应到哪个新的node(就是代码中的Map<Node, Node>,索引为copy前的node,值为copy之后的node)

代码

/*
// Definition for a Node.
class Node {
    int val;
    Node next;
    Node random;

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

class Solution {
    Map<Node, Node> nodes = new HashMap<>();
    
    public Node copyRandomList(Node head) {
        if(head == null)
            return null;
        
        Node newNode = new Node(head.val);
        nodes.put(head, newNode);
        newNode.next = copyRandomList(head.next);
        
        Node random = head.random;
        if(random == null)
            newNode.random = null;
        else
            newNode.random = nodes.get(random);
                   
        return newNode;
    }
}

better思路&代码

submission里面有一个很好的思路!
它是利用位置关系进行操作,不太好说明,就用图来表示吧

假设这是原始的list,random没有表现出来
在这里插入图片描述
在每个原始node后面插入新node,也就是这样
在这里插入图片描述
在这种情况下,新node和旧node的位置关系是相同的!也就是在处理random的时候,假设我们已知oldNode.random,那么与oldNode对应的newNode (=oldNode.next)的random就是

  • oldNode.random.next

也就是

oldNode.next.random = oldNode.random.next

完美利用了位置关系!
最后再交叉地获取newNode就可以了!

完整代码如下

class Solution {
    public Node copyRandomList(Node head) {
        Node dumb = new Node(-1);
        dumb.next = head;
        
        Node cur = dumb.next;
        while (cur != null) {
            Node temp = new Node(cur.val);
            temp.next = cur.next;
            cur.next = temp;
            cur = cur.next.next;
        }
        
        cur = dumb.next;
        while (cur != null) {
            if (cur.random != null) {
                cur.next.random = cur.random.next;
            }
            
            cur = cur.next.next;
        }
        
        Node newDumb = new Node(-1);
        Node cur1 = dumb;
        Node cur2 = newDumb;
        while (cur1.next != null) {
            cur1 = cur1.next;
            cur2.next = cur1.next;
            cur1.next = cur1.next.next;
            cur2 = cur2.next;
        }
        
        return newDumb.next;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值