作者: 负雪明烛
id: fuxuemingzhu
个人公众号:负雪明烛
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode-cn.com/problems/copy-list-with-random-pointer/

题目描述

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

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

例如,如果原链表中有 XY 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 xy ,同样有 x.random --> y

返回复制链表的头节点。

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

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

你的代码 接受原链表的头节点 head 作为传入参数。

示例 1:

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

示例 2:

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

示例 3:

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

示例 4:

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

提示:

  • 0 <= n <= 1000
  • -10000 <= Node.val <= 10000
  • Node.random 为空(null)或指向链表中的节点。

题目大意

复制一个复杂链表,这个复杂链表是指出了值和next指针外,还有一个random指针可能指向任何位置的链表节点或空。

解题方法

这个题是剑指Offer的“面试题26:复杂链表的复制”原题。书上的做法是在原先的每个节点之后进行复制了一个节点,从而构成了一个二倍长度的单链表,然后再修改random指针。这样做的好处是没有使用额外空间,但是缺点是做法比较麻烦。

一个更简洁的做法是使用 HashMap,在这个 HashMap 里,记录了 老链表的每个节点 和 新链表的每个节点的 对应关系。

第一步,先构造了一个纯next的链表;
第二部,对链表再次循环,修改每个节点的 random 的指针了。

Python 代码如下:

"""
# Definition for a Node.
class Node(object):
def __init__(self, val, next, random):
self.val = val
self.next = next
self.random = random
"""
class Solution(object):
def copyRandomList(self, head):
"""
:type head: Node
:rtype: Node
"""
nodeDict = dict()
dummy = Node(0, None, None)
nodeDict[head] = dummy
newHead, pointer = dummy, head
while pointer:
node = Node(pointer.val, pointer.next, None)
nodeDict[pointer] = node
newHead.next = node
newHead, pointer = newHead.next, pointer.next
pointer = head
while pointer:
if pointer.random:
nodeDict[pointer].random = nodeDict[pointer.random]
pointer = pointer.next
return dummy.next

C++ 代码如下:

/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random; Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/ class Solution {
public:
Node* copyRandomList(Node* head) {
if (!head) return nullptr;
unordered_map<Node*, Node*> copyMap;
Node* newHead = new Node(head->val);
Node* moveOld = head;
Node* moveNew = newHead;
while (moveOld) {
copyMap[moveOld] = moveNew;
moveNew->next = moveOld->next ? new Node(moveOld->next->val) : nullptr;
moveNew = moveNew->next;
moveOld = moveOld->next;
}
moveOld = head;
moveNew = newHead;
while (moveOld) {
moveNew->random = copyMap[moveOld->random];
moveNew = moveNew->next;
moveOld = moveOld->next;
}
return newHead;
}
};

日期

2018 年 6 月 23 日 —— 美好的周末要从刷题开始
2021 年 7 月 22 日 —— 最近天气一直是阴天下雨,希望天气好点

【LeetCode】138. Copy List with Random Pointer 复制带随机指针的链表 解题报告(Python)的更多相关文章

  1. 138 Copy List with Random Pointer 复制带随机指针的链表

    给出一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点.返回一个深拷贝的链表. 详见:https://leetcode.com/problems/copy-list- ...

  2. Leetcode138. Copy List with Random Pointer复制带随机指针的链表

    给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点. 要求返回这个链表的深度拷贝. 方法一: class Solution { public: RandomLis ...

  3. [LeetCode] 138. Copy List with Random Pointer 拷贝带有随机指针的链表

    A linked list is given such that each node contains an additional random pointer which could point t ...

  4. Java for LeetCode 138 Copy List with Random Pointer

    A linked list is given such that each node contains an additional random pointer which could point t ...

  5. [LeetCode] 138. Copy List with Random Pointer 拷贝带随机指针的链表

    A linked list is given such that each node contains an additional random pointer which could point t ...

  6. leetcode 138. Copy List with Random Pointer ----- java

    A linked list is given such that each node contains an additional random pointer which could point t ...

  7. leetcode 138. Copy List with Random Pointer复杂链表的复制

    python代码如下: # Definition for singly-linked list with a random pointer. # class RandomListNode(object ...

  8. Leetcode#138 Copy List with Random Pointer

    原题地址 非常巧妙的方法,不需要用map,只需要O(1)的额外存储空间,分为3步: 1. 先复制链表,但是这个复制比较特殊,每个新复制的节点添加在原节点的后面,相当于"加塞"2. ...

  9. [leetcode]138. Copy List with Random Pointer复制带有随机指针的链表

    public RandomListNode copyRandomList(RandomListNode head) { /* 深复制,就是不能只是复制原链表变量,而是做一个和原来链表一模一样的新链表, ...

随机推荐

  1. open 函数小结

    umask 掩码 open 函数的时候需要注意,掩码去反之后和设置的值想与,得到真正的值. 可以在命令行 使用umask 来查询 umask 000 设置掩码

  2. 【Redis】过期键删除策略和内存淘汰策略

    Redis 过期键策略和内存淘汰策略 目录 Redis 过期键策略和内存淘汰策略 设置Redis键过期时间 Redis过期时间的判定 过期键删除策略 定时删除 惰性删除 定期删除 Redis过期删除策 ...

  3. Identity Server 4 从入门到落地(七)—— 控制台客户端

    前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...

  4. day02 Rsyuc备份服务器

    day02 Rsyuc备份服务器 一.备份 1.什么是备份 备份就是把重要的数据或者文件复制一份保存到另一个地方,实现不同主机之间的数据同步 一般数据比较重要的情况下,数据如果丢失很容易找不回来了的, ...

  5. postgresql安装部署

    一.下载安装: 1.下载: 官网下载地址:https://www.postgresql.org/download/linux/redhat/ 也可以用这个:https://www.enterprise ...

  6. 格式化代码(Eclipse 格式化代码块快捷键:Ctrl+Shift+F)

    1.格式化java代码 : ①Ctrl+Shift+F 但是我们会遇到按 Ctrl+Shift+F不起作用的时候?       Ctrl+Shift+F 在搜狗拼音里是简繁替换.一旦安装搜狗拼音这个快 ...

  7. final&static

    final 1.final修饰类,那么该类不能有子类,那么也就没有子类重写父类的方法,也就没有多态 2.final修饰成员变量,那么成员变量要么显式赋值(用第一种),要么在构造方法中赋值 无论哪一种, ...

  8. treeTable实现排序

    /* * * TreeTable 0.1 - Client-side TreeTable Viewer! * @requires jQuery v1.3 * * Dual licensed under ...

  9. 什么是maven(二)

    转自博主--一杯凉茶 maven项目构建ssh工程(父工程与子模块的拆分与聚合)   前一节我们明白了maven是个什么玩意,这一节就来讲讲他的一个重要的应用场景,也就是通过maven将一个ssh项目 ...

  10. 如何在子线程中更新UI

    一:报错情况 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that creat ...