链表/138. 复制带随机指针的链表

342 阅读3分钟

题目描述

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的 深拷贝。 

我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

val:一个表示 Node.val 的整数。 random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。  

示例 1:

1

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]] 输出:[[7,null],[13,0],[11,4],[10,2],[1,0]] 示例 2:

2

输入:head = [[1,1],[2,1]] 输出:[[1,1],[2,1]] 示例 3:

3

输入:head = [[3,null],[3,0],[3,null]] 输出:[[3,null],[3,0],[3,null]] 示例 4:

输入:head = [] 输出:[] 解释:给定的链表为空(空指针),因此返回 null。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/co… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

js

/**
 * // Definition for a Node.
 * function Node(val, next, random) {
 *    this.val = val;
 *    this.next = next;
 *    this.random = random;
 * };
 */
function Node(val, next, random) {
    this.val = val;
    this.next = next;
    this.random = random;
}
//生成head
let listA = new Node(7,null,null);
(function(){
    let la = listA,i=0, obj={};
    obj[i++] = la;
    la.next = new Node(13,null,null);
    la = la.next;
    obj[i++] = la;
    la.next = new Node(11,null,null);
    la = la.next;
    obj[i++] = la;
    la.next = new Node(10,null,null);
    la = la.next;
    obj[i++] = la;
    la.next = new Node(1,null,null);
    la = la.next;
    obj[i++] = la;
    obj[1].random = obj[0];
    obj[2].random = obj[4];
    obj[3].random = obj[2];
    obj[4].random = obj[0];
})();
//copyRandomList(listA)
/**
 * @param {Node} head
 * @return {Node}
 */
var copyRandomList0 = function (head) {
    let newHead = new Node(-1),
        na = newHead,
        la = head,
        index = 0,
        obj = {};


    while (la) {
        obj[index++] = {
            map: la,
            random: null
        };
        la = la.next;
    }
    la = head;
    for (let key in obj) {
        for (let k in obj) {
            if (obj[key].map.random === obj[k].map) {
                obj[key].random = k;
                break;
            }
        }
    }
    la = head,
        index = 0;
    while (la) {

        na.next = new Node(la.val, null, obj[index].random || null);
        na = na.next;
        obj[index++].map = na;
        la = la.next;
    }
    na = newHead.next;
    while (na) {
        if (na.random) {
            na.random = obj[na.random].map;
        }
        na = na.next;
    }
    // console.log(na)
    return newHead.next;
};
var copyRandomList1 = function (head) {
    let newHead = new Node(-1),
        na = newHead,
        la = head,
        index = 0,
        obj = {};

    //这里就是做了个映射
    //通过对比得到random是第几个节点
    //obj map存储复制后的节点
    while (la) {
        let random = null;

        if (la.random) {
            let k = head,
                i = 0;

            while (k) {
                if (la.random === k) {
                    random = i;
                    break;
                }
                k = k.next;
                i++;
            }
        }

        na.next = new Node(la.val, null, random);
        na = na.next;
        obj[index++] = na;
        la = la.next;
    }
    //根据映射来赋值random
    na = newHead.next;
    while (na) {
        if (na.random !== null) {
            na.random = obj[na.random];
        }
        na = na.next;
    }
    return newHead.next;
};
//精髓就是 把当前节点作为key 深复制的新节点作为值
//然后 节点的random不为空时 去map里取对应 深复制的节点作为新链表节点的random
var copyRandomList2 = function (head) {
    let newHead = new Node(-1),
        na = newHead,
        la = head,
        map = new Map();

    while (la){
        na.next = new Node(la.val,null,null);
        na = na.next;
        map.set(la,na);
        la = la.next;
    }
    la = head,
    na = newHead.next;
    while (la){
        la.random && (na.random = map.get(la.random));
        la = la.next;
        na = na.next;
    }
    return newHead.next;
};
//原理就是复制当前节点并成为当前节点的next节点
//就形成了 A-A-B-B-C-C-null,前是原节点 后是复制的节点
//仔细观察 可以看出 原节点A的random 指向的节点的next 是复制后的节点
//所以当前节点存在random时 那么当前节点的next节点的random 就等于 当前节点的random节点的next
//最后再取出复制的节点并在原链表里删除
var copyRandomList = function (head) {
    let lista = head,node=null,newHead = new Node(-1,null,null);

    while (lista){
        let tem = lista.next;

        node = new Node(lista.val,null,null);
        lista.next = node;
        node.next = tem;

        lista = tem;
    }
    lista = head;
    while (lista){
        if (lista.random){
            lista.next.random = lista.random.next;
        }
        lista = lista.next.next;
    }
    node = newHead;
    lista = head;
    while (lista){
        node.next = lista.next;
        node = node.next;
        lista.next = node.next;
        lista = lista.next;
    }
    return newHead;
};

python

"""
# Definition for a Node.

"""
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        lista,newHead = head,Node(-1)

        while lista:
            tem = lista.next
            node = Node(lista.val)
            node.next = lista.next
            lista.next = node
            lista = tem
        
        lista = head

        while lista:
            if lista.random:
                lista.next.random = lista.random.next
            lista = lista.next.next

        lista = head
        node = newHead

        while lista:
            node.next = lista.next
            node = node.next
            lista.next = node.next
            lista = lista.next
        
        return newHead.next
    def copyRandomList1(self, head: 'Node') -> 'Node':
        lista,newHead,index,obj = head,Node(-1),0,{}
        nlist = newHead

        while lista:
            random = None
            if lista.random:
                k,i = head,0
                while k:
                    if lista.random == k:
                        random = i
                        break
                    k = k.next
                    i+=1
            nlist.next = Node(lista.val,None,random)
            nlist = nlist.next
            obj[index] = nlist
            index+=1
            lista = lista.next
        nlist = newHead.next
        while nlist:
            if nlist.random != None:
                nlist.random = obj[nlist.random]
            nlist = nlist.next
        return newHead.next

#生成题的链表
listA = Node(7)
la = listA
i=0
obj={}
obj[i] = la
i+=1
la.next = Node(13)
la = la.next
obj[i] = la
i+=1
la.next = Node(11)
la = la.next
obj[i] = la
i+=1
la.next = Node(10)
la = la.next
obj[i] = la
i+=1
la.next = Node(1)
la = la.next
obj[i] = la
i+=1
obj[1].random = obj[0]
obj[2].random = obj[4]
obj[3].random = obj[2]
obj[4].random = obj[0]
print(listA == Solution().copyRandomList(listA))

目的只是为了记录一下

python版本基本就是复刻的js。主要是为了熟悉一下python

源码存储地址