问题描述

请实现 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%的用户

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

最新文章

  1. 安装使用Oracle OSWbb/OSWbba工具
  2. KMP 算法
  3. 通俗理解T检验和F检验
  4. sky
  5. 如何根据不同的浏览器写不同的css样式达到兼容
  6. 设置session失效的几种方法
  7. ARM地址映射
  8. uva1637Double Patience
  9. Java中的DeskTop类
  10. CentOS安装SetupTools(easy_install)
  11. sed写的命令收集
  12. Hadoop的初步理解
  13. sourcetree的使用
  14. django连接sqlserver
  15. remote: Repository not found. fatal: repository &#39;https://github.com/***/***.git/&#39; not found
  16. 快速创建一个 spring mvc 示例
  17. Quart2D矩阵变换
  18. Mono.Cecil 修改目标.NET的IL代码保存时报异常的处理。
  19. 【分层最短路】Magical Girl Haze
  20. tableLayoutPanel 列宽度设置

热门文章

  1. Kali渗透安卓手机
  2. CF740B Alyona and flowers 题解
  3. 存储技术之ceph了解
  4. 账号不允许远程访问服务器上的mysql数据库的解决办法host is not allowed to connect to this mysql
  5. centos使用shell脚本定时备份docker中的mysql数据库
  6. nim_duilib(13)之添加fmt库
  7. 【LeetCode】1047. Remove All Adjacent Duplicates In String 解题报告(Python)
  8. 【九度OJ】题目1199:找位置 解题报告
  9. 【LeetCode】38. 外观数列 Count and Say
  10. 【LeetCode】682. Baseball Game 解题报告(Python)