问题描述

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例 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。
提示: -10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。

问题分析

分为以下三个步骤:

  1. 在原链表的每个节点后面拷贝出一个新的节点。
  2. 依次给新的节点的随机指针赋值,而且这个赋值非常容易 cur->next->random = cur->random->next。
  3. 断开链表可得到深度拷贝后的新链表。

    举个例子来说吧,比如原链表是 1(NULL) -> 2(1) -> 3(NULL) -> 4(3),括号中是其 random 指针指向的结点,那么这个解法是首先比遍历一遍原链表,在每个结点后拷贝一个同样的结点,但是拷贝结点的 random 指针仍为空,则原链表变为 1(NULL) -> 1(null) -> 2(1) -> 2(null) -> 3(NULL) -> 3(NULL) -> 4(2) ->4(NULL)。然后第二次遍历,是将拷贝结点的 random 指针赋上正确的值,则原链表变为 1(NULL) -> 1(NULL) -> 2(1) -> 2(1) -> 3(NULL) -> 3(NULL) -> 4(2) -> 4(2),注意赋值语句为:cur->next->random = cur->random->next;这里的 cur 是原链表中结点,cur->next 则为拷贝链表的结点,cur->next->random 则为拷贝链表的 random 指针。cur->random 为原链表结点的 random 指针指向的结点,因为其指向的还是原链表的结点,所以我们要再加个 next,才能指向拷贝链表的结点。最后再遍历一次,就是要把原链表和拷贝链表断开即可

代码

/*
// 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 NULL;
Node* cur = head;
//将每个链表的节点后面都拷贝一个相同数值的节点,但拷贝节点的random为空
while(cur)
{
Node* t = new Node(cur->val);
t->next = cur->next;
cur->next = t;
cur = t->next;
}
cur = head;
//对拷贝节点的random进行赋值
while(cur)
{
if(cur->random)
cur->next->random = cur->random->next;//实际上指向的是cur->random,这个是由cur->random拷贝出来的那一个
cur = cur->next->next;
}
cur = head;
//将拷贝的节点分离出来
Node* ans = cur->next;
Node* t = ans;
while(cur)
{
cur->next = cur->next->next;
cur = cur->next;
if(t->next)
{
t->next = t->next->next;
t = t->next;
}
}
return ans;
}
};

结果

执行用时 :16 ms, 在所有 C++ 提交中击败了65.68%的用户
内存消耗 :11 MB, 在所有 C++ 提交中击败了100.00%的用户

当然还有递归和哈希表的解法,后面补充。

《剑指offer》面试题35. 复杂链表的复制的更多相关文章

  1. 剑指offer 面试题35.复杂链表的复制

    时间O(N),空间O(N) /* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomList ...

  2. 剑指offer面试题26-复杂链表的复制

    题目: 请实现函数ComplexListNode* Clone(ComplexListNode* pHead).复制一个复杂链表. 在复杂链表中.每个节点除了一个m_pNext指针指向下一个节点外,另 ...

  3. 剑指Offer - 九度1524 - 复杂链表的复制

    剑指Offer - 九度1524 - 复杂链表的复制2014-02-07 01:30 题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点 ...

  4. 剑指Offer面试题:14.链表的倒数第k个节点

    PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善. 一.题目:链表的倒数第k个节点 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题 ...

  5. C++版 - 剑指Offer 面试题35:第一个只出现一次的字符 解题报告(华为OJ034-找出字符串中第一个只出现一次的字符)

    面试题35:第一个只出现一次的字符 题目:在一个字符串中找到第一个只出现一次的字符.如输入abaccdeff,则输出b.(2006年google的一道笔试题.) 分析: 首先应向确认一下是ASCII字 ...

  6. 剑指Offer:面试题16——反转链表(java实现)

    问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = n ...

  7. 【剑指offer 面试题15】链表中倒数第K个结点

    思路: 定义两个指针同时指向head,第一个指针先走K-1步,随后二个指针同时移动,当第一个指针到末尾处时,第二个指针所指向的即为倒数第K个结点. #include <iostream> ...

  8. 剑指offer面试题15:链表中倒数第K个节点

    题目:输入一个链表,输出该链表的倒数第K个节点.为了符合大多数人的习惯,本题从1开始计数,即链表尾节点是倒数第一个节点. 解题思路: 解法一:一般情况下,单向链表无法从后一个节点获取到它前面的节点,可 ...

  9. 剑指offer——面试题23:链表中环的入口节点

    函数: ListNode* MeetingNode(ListNode* pHead) { if(pHead==nullptr) return nullptr; ListNode* quickNode= ...

  10. 剑指offer——面试题18:删除链表的节点

    #include"List.h" void DeleteNode(ListNode** pHead,ListNode* pToBeDeleted) { if(*pHead==nul ...

随机推荐

  1. 使用.NET 6开发TodoList应用(2)——项目结构搭建

    为了不影响阅读的体验,我把系列导航放到文章最后了,有需要的小伙伴可以直接通过导航跳转到对应的文章 : P TodoList需求简介 首先明确一下我们即将开发的这个TodoList应用都需要完成什么功能 ...

  2. Linux(centos7)安装redis并设置redis开机自启动

    1.下载redis安装包 wget http://download.redis.io/releases/redis-4.0.6.tar.gz 2.解压安装包 tar -zxvf redis-4.0.6 ...

  3. Windows系统安装Redis服务

    下载压缩包,登录 https://github.com/MicrosoftArchive/redis/releases  下载Redis-x64-3.0.504.zip 我也上传了一份  https: ...

  4. 【LeetCode】226. Invert Binary Tree 翻转二叉树(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 迭代 日期 题目地址: https://lee ...

  5. 【LeetCode】121. Best Time to Buy and Sell Stock 解题报告(Java & Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 Java解法 Python解法 C++ 解法 日期 ...

  6. 【九度OJ】题目1185:特殊排序 解题报告

    [九度OJ]题目1185:特殊排序 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1185 题目描述: 输入一系 ...

  7. 【九度OJ】题目1187:最小年龄的3个职工 解题报告

    [九度OJ]题目1187:最小年龄的3个职工 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1187 题目描述: 职工有职工号,姓名, ...

  8. 【LeetCode】386. Lexicographical Numbers 解题报告(Python)

    [LeetCode]386. Lexicographical Numbers 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博 ...

  9. PLSQL到期处理

    一.输入指令"regedit"打开注册表 二.指令输入完毕后,按回车键,会进入这个界面. 三.注册表里按HKEY_CURRENT_USER\Software\Allround Au ...

  10. 【C\C++笔记】register寄存器关键字

    使用寄存器变量提高运行速度 1未使用寄存器组 #include<stdio.h> int main(){ unsigned long a=0; for(int i=0;i<10000 ...