[剑指offer]面试题第[35]题[Leetcode][第138题][JAVA][复杂链表的复制][暴力][HashMap][复制链表]

【问题描述】[中等]

在这里插入图片描述

【解答思路】

1. 暴力 直接复制

将链表从头节点一个一个复制下去,
在根据记录的总长度num,遍历原来的每个节点的random到尾节点个数count,然后顺序遍历找到新链表的该指针在num-count上 。
时间复杂度:O(N^2) 空间复杂度:O(N)

class Solution {public Node copyRandomList(Node head) {if(head==null) return head;Node newHead=new Node(head.val);Node keep=newHead;Node node=head.next;int num=1;//记录节点数while(node!=null){keep.next=new Node(node.val);node=node.next;keep=keep.next;num++;}keep.next=null;Node newn=newHead;Node oldn=head;//n r 定位randomNode n;Node r;int count;while (oldn!=null){n= oldn.random;//进行循环找到酒链表random指向的位置nr=newHead;count=0;//计算出旧链表n距离尾节点个数while (n!=null){n=n.next;count++;}//计算旧的random在链表中的位置  利用新旧链表新旧位置相同的原理for(int res=num-count;res>0;res--){r=r.next;}newn.random=r;//遍历新旧链表oldn=oldn.next;newn=newn.next;}return newHead;}
}作者:zhao-1z
链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/javaliang-chong-xie-fa-by-zhao-1z/
2. HashMap O(N)空间

在这里插入图片描述
在这里插入图片描述

**时间复杂度:O(N) 空间复杂度:O(N) **
在这里插入图片描述

/*
// Definition for a Node.
class Node {public int val;public Node next;public Node random;public Node() {}public Node(int _val,Node _next,Node _random) {val = _val;next = _next;random = _random;}
};
*/
public class Solution {// Visited dictionary to hold old node reference as "key" and new node reference as the "value"HashMap<Node, Node> visited = new HashMap<Node, Node>();public Node getClonedNode(Node node) {// If the node exists thenif (node != null) {// Check if the node is in the visited dictionaryif (this.visited.containsKey(node)) {// If its in the visited dictionary then return the new node reference from the dictionaryreturn this.visited.get(node);} else {// Otherwise create a new node, add to the dictionary and return itthis.visited.put(node, new Node(node.val, null, null));return this.visited.get(node);}}return null;}public Node copyRandomList(Node head) {if (head == null) {return null;}Node oldNode = head;// Creating the new head node.Node newNode = new Node(oldNode.val);this.visited.put(oldNode, newNode);// Iterate on the linked list until all nodes are cloned.while (oldNode != null) {// Get the clones of the nodes referenced by random and next pointers.newNode.random = this.getClonedNode(oldNode.random);newNode.next = this.getClonedNode(oldNode.next);// Move one step ahead in the linked list.oldNode = oldNode.next;newNode = newNode.next;}return this.visited.get(head);}
}作者:LeetCode
链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/fu-zhi-dai-sui-ji-zhi-zhen-de-lian-biao-by-leetcod/
3. HashMap O(N)空间

遍历第一遍链表,我们不考虑链表之间的相互关系,仅仅生成所有节点,然后把它存到 HashMap 中,h(val) 作为 key,Node 作为 value。

遍历第二遍链表,将之前生成的节点取出来,更新它们的 next 和 random 指针。

时间复杂度:O(N) 空间复杂度:O(N)

public Node copyRandomList(Node head) {if (head == null) {return null;}HashMap<Node, Node> map = new HashMap<>();Node h = head;while (h != null) {Node t = new Node(h.val); map.put(h, t);h = h.next;}h = head;while (h != null) {if (h.next != null) {map.get(h).next = map.get(h.next);}if (h.random != null) {map.get(h).random = map.get(h.random);}h = h.next;}return map.get(head);
}作者:windliang
链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-32/
4. HashMap O(N)空间

只遍历一次链表。
核心思想就是延迟更新它的 next。

1 -> 2 -> 3
用 cur 指向已经生成的节点的末尾
1 -> 2
^
c
然后将 3 构造完成
最后将 2 的 next 指向 3
1 -> 2 -> 3
^
c
期间已经生成的节点存到 HashMap 中,第二次遇到的时候直接从 HashMap 中拿

时间复杂度:O(N) 空间复杂度:O(N)

public Node copyRandomList(Node head) {if (head == null) {return null;}HashMap<Node, Node> map = new HashMap<>();Node h = head;Node cur = new Node(-1); //空结点,dummy 节点,为了方便头结点计算while (h != null) {//判断当前节点是否已经产生过if (!map.containsKey(h)) {Node t = new Node(h.val);map.put(h, t);}//得到当前节点去更新它的 random 指针Node next = map.get(h);if (h.random != null) {//判断当前节点是否已经产生过if (!map.containsKey(h.random)) {next.random = new Node(h.random.val);map.put(h.random, next.random);} else {next.random = map.get(h.random);}}//将当前生成的节点接到 cur 的后边cur.next = next;cur = cur.next;h = h.next;}return map.get(head);
}
5. O(1)空间 (用原链表的 next 域保存新生成的节点)

主要解决的问题就是我们生成节点以后,当更新它的 random 的时候,怎么找到之前生成的节点,前两种解法用了 HashMap 全部存起来,这里的话可以利用原来的链表的指针域。

主要需要三步。

  1. 生成所有的节点,并且分别插入到原有节点的后边
  2. 更新插入节点的 random
  3. 将新旧节点分离开来
    在这里插入图片描述
    在这里插入图片描述

时间复杂度:O(N) 空间复杂度:O(1)

public Node copyRandomList(Node head) {if (head == null) {return null;}Node l1 = head;Node l2 = null;//生成所有的节点,并且分别插入到原有节点的后边while (l1 != null) {l2 = new Node(l1.val);l2.next = l1.next;l1.next = l2;l1 = l1.next.next;}//更新插入节点的 randoml1 = head;while (l1 != null) {if (l1.random != null) {l1.next.random = l1.random.next;}l1 = l1.next.next;}l1 = head;Node l2_head = l1.next;//将新旧节点分离开来while (l1 != null) {l2 = l1.next;l1.next = l2.next;if (l2.next != null) {l2.next = l2.next.next;}l1 = l1.next;}return l2_head;
}
/*
// Definition for a Node.
class Node {public int val;public Node next;public Node random;public Node() {}public Node(int _val,Node _next,Node _random) {val = _val;next = _next;random = _random;}
};
*/
public class Solution {public Node copyRandomList(Node head) {if (head == null) {return null;}// Creating a new weaved list of original and copied nodes.Node ptr = head;while (ptr != null) {// Cloned nodeNode newNode = new Node(ptr.val);// Inserting the cloned node just next to the original node.// If A->B->C is the original linked list,// Linked list after weaving cloned nodes would be A->A'->B->B'->C->C'newNode.next = ptr.next;ptr.next = newNode;ptr = newNode.next;}ptr = head;// Now link the random pointers of the new nodes created.// Iterate the newly created list and use the original nodes' random pointers,// to assign references to random pointers for cloned nodes.while (ptr != null) {ptr.next.random = (ptr.random != null) ? ptr.random.next : null;ptr = ptr.next.next;}// Unweave the linked list to get back the original linked list and the cloned list.// i.e. A->A'->B->B'->C->C' would be broken to A->B->C and A'->B'->C'Node ptr_old_list = head; // A->B->CNode ptr_new_list = head.next; // A'->B'->C'Node head_old = head.next;while (ptr_old_list != null) {ptr_old_list.next = ptr_old_list.next.next;ptr_new_list.next = (ptr_new_list.next != null) ? ptr_new_list.next.next : null;ptr_old_list = ptr_old_list.next;ptr_new_list = ptr_new_list.next;}return head_old;}
}
6. O(1)空间 (用原链表的 random域保存新生成的节点)

可以利用原链表的 random 域把新生成的节点保存起来。
主要还是三个步骤。

  1. 生成所有的节点,将它们保存到原链表的 random 域,同时利用新生成的节点的 next 域保存原链表的 random。
  2. 更新新生成节点的 random 指针。
  3. 恢复原链表的 random 指针,同时更新新生成节点的 next 指针。

时间复杂度:O(N) 空间复杂度:O(1)

public Node copyRandomList(Node head) {if (head == null) {return null;}Node l1 = head;Node l2 = null;//生成所有的节点,讲它们保存到原链表的 random 域,//同时利用新生成的节点的 next 域保存原链表的 random。while (l1 != null) {l2 = new Node(l1.val);l2.next = l1.random;l1.random = l2;l1 = l1.next;}l1 = head;//更新新生成节点的 random 指针。while (l1 != null) {l2 = l1.random;l2.random = l2.next != null ? l2.next.random : null;l1 = l1.next;}l1 = head;Node l2_head = l1.random;//恢复原链表的 random 指针,同时更新新生成节点的 next 指针。while (l1 != null) {l2 = l1.random;l1.random = l2.next;l2.next = l1.next != null ? l1.next.random : null;l1 = l1.next;}return l2_head;
}

【总结】

1.思路1暴力O(N^2)-> 思路2.3.4 HashMap O(N)->思路5.6 复制链表O(1)
2.链表操作的核心思想就是,在改变某一个节点的指针域的时候,一定要把该节点的指针指向的节点用另一个指针保存起来,以免造成丢失。
3.链表 画图

转载链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-32/
转载链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-32/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/425131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第二十七期:德国工业4.0眼里“工业互联网”与“智能制造”

工业4.0在德国被认为是第四次工业革命&#xff0c;主要是指&#xff0c;在“智能工厂”利用“智能备”将“智能物料”生产成为“智能产品”&#xff0c;整个过程贯穿以“网络协同”&#xff0c;从而提升生产效率&#xff0c;缩短生产周期&#xff0c;降低生产成本。 工业4.0在德…

[剑指offer]面试题第[36]题[JAVA][二叉搜索树与双向链表][递归]

【问题描述】[中等] 【解答思路】 中序遍历 时间复杂度&#xff1a;O(N) 空间复杂度&#xff1a;O(N) class Solution {Node pre, head;public Node treeToDoublyList(Node root) {if(root null) return null;dfs(root);head.left pre;pre.right head;return head;}void …

深度学习第一次课-数学

说明&#xff1a;本文是七月算法5月深度学习班第一次课听课笔记。只记录关键知识点&#xff0c;有些没具体展开。帮助复习用。文中使用了老师课件中的公式。 微积分 导数 定义常用函数导数导数法则加法 乘法 除法 链式法则一元函数与多元函数一阶导 一元函数 f(x) 多元函…

深度学习第三次课-梯度下降与反向传播

梯度下降 损失函数可视化 得分函数 fW*X损失函数 cW*X-y 目标 损失函数最小 最优化过程可视化 一维二维 热力图如果损失函数是一个凸函数&#xff0c;例如SVM。凸函数 正系数加和凸函数神经网络 costfunction 非凸 因为系数有正有负。凸优化与最优化…

[Leetcode][第1025题][JAVA][除数博弈][数学][递推]

【问题描述】[中等] 【解答思路】 1. 数学证明 找规律 时间复杂度&#xff1a;O(1) 空间复杂度&#xff1a;O(1) 2. 递推 时间复杂度&#xff1a;O(N) 空间复杂度&#xff1a;O(1) class Solution {public boolean divisorGame(int N) {boolean[] f new boolean[N 5];f[1]…

[Leetcode][第410题][JAVA][分割数组的最大值][动态规划][二分]

【问题描述】[中等] 【解答思路】 1. 动态规划 第 1 步&#xff1a;设计状态 令 f[i][j] 表示将数组的前 i 个数分割为 j 段所能得到的最大连续子数组和的最小值。 &#xff08; i ≥ j &#xff09; 第 2 步&#xff1a;状态转移方程 第 3 步&#xff1a;考虑初始化 f[i][…

数据结构与算法分析

本系列的笔记基于七月算法的《求职面试》课程以及《数据结构域算法分析-java语言描述》第2版&#xff0c;做学习笔记。 以下是这系列的目录。每个专题只做笔记&#xff0c;不求每个专题都要深入到很深很深。算法分析 表 栈 队列 并查集 哈希表 树 堆 图论 递归 深度优…

[算法][算法复杂度]常用算法复杂度速查表

复杂度通常会使用大 -O记号来表示&#xff0c;比如快速排序的平均时间复杂度是 O(nlog(n))。虽然我们应该做「理解派」&#xff0c;但是即使每个算法/数据结构都理解了&#xff0c;不时仍有可能忘记具体某个算法/数据结构的复杂度&#xff08;特别是在最好、最坏和平均情形下的…

十张伟大的科学瞬间

题图&#xff1a; 搭载 ORBCOMM OG2-M1 卫星的猎鹰 9 号运载火箭发射&#xff0c;人类一直很渺小。 ▎2019 更新 北京时间 2019 年 4 月 10 日 21 点&#xff0c;人类首张黑洞照片正式发布&#xff01; 这次的直接成像除了帮助我们直接确认了黑洞的存在&#xff0c;同时也通过模…

[Leetcode][第329题][JAVA][矩阵中的最长递增路径][DFS][拓扑排序]

【问题描述】[中等] 【解答思路】 1. 记忆化深度优先搜索 复杂度 class Solution {public int[][] dirs {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};public int rows, columns;public int longestIncreasingPath(int[][] matrix) {if (matrix null || matrix.length 0 || matri…

第二十八期:阿里云VS腾讯云 谁才是中国未来的云计算之王?

阿里云早在 2009 年就已经开始布局云计算领域&#xff0c;具有先发优势。据统计&#xff0c;40% 的中国 500 强企业、近一半中国上市公司、80% 中国科技类公司是阿里云的客户。而腾讯云基于腾讯自身在游戏、视频、社交、出行等业务的强势地位&#xff0c;一路奋起直追&#xff…

[小技巧][JAVA][转换]字符数组char[]与字符串String之间互相转换

1.字符数组转为字符串 方法1&#xff1a;直接在构造String时转换。 char[] data {‘a’, ‘b’, ‘c’}; String str new String(data);方法2&#xff1a;调用String类的方法转换。 String s String.valueOf(char[] ch)2.字符串转为字符数组 情况一&#xff1a;如果是”a…

CentOS 7 Apache服务的安装与配置(转)

https://blog.51cto.com/13525470/2070375 一、Apache简介 Apache 是一个知名的开源Web服务器。早期的Apache服务器由Apache Group来维护&#xff0c;直到1999年6月Apache Group在美国德拉瓦市成立了非盈利性组织的公司&#xff0c;即Apache软件基金会&#xff08;Apache Softw…

第二十九期:全球首部AI交响变奏曲问世,AI技术应用再拓边界

人工智能技术&#xff0c;史上第一次升级到了复杂音乐的创作领域&#xff1a;交响曲。 全球首部 AI 交响变奏曲《我和我的祖国》&#xff0c;昨晚已由深圳交响乐团全球首演&#xff0c;它的出品方是中国平安人工智能研究院。 此前&#xff0c;你可能了解过 Google 的 Magenta、…

第三十期:BAT 为什么都看上了重庆?

一个城市朝向智能化创新的方向发展&#xff0c;一把手的重视是非常重要的。 文&#xff1a;I/O 重庆&#xff0c;作为我国中西部地区唯一的直辖市和国家中心城市&#xff0c;正在新一轮科技发展浪潮中扮演着越来越亮眼的角色。 尤其是近两个月来&#xff0c;重庆在推动科技创新…

第三十一期:世界上有四类人永远不可能成为编程界牛人(个人见解,欢迎补充)

本人歌谣&#xff0c;出来工作也有两年了。大学挂科无数&#xff0c;出来想搞技术。平时也就是以工作学习的知识为主&#xff0c;无聊的时候就会学习一些关于科技的知识。 在这本人给大家传授一些学习编程的心得体会&#xff0c;供大家分享交流&#xff1a; 1.没有专注力和恒心…

[Java]==和equals()的区别(按照数据类型区分)

背景知识 【引用类型】 复合数据类型是引用类型 **1.基本数据类型&#xff0c;也称原始数据类型。**byte,short,char,int,long,float,double,boolean 他们之间的比较&#xff0c;应用双等号&#xff08;&#xff09;,比较的是他们的值。 基本数据类型比较&#xff0c; 和 …

第三十二期:如何摆脱「技术思维」的惯性?

虽然从标题上看&#xff0c;这篇文章是写给“技术人”的&#xff0c;但 从广义上来说&#xff0c;只要你是一位以理性见长的人&#xff0c;那么这篇文章要讲的东西可能会与你有关。 虽然从标题上看&#xff0c;这篇文章是写给“技术人”的&#xff0c;但 从广义上来说&#xff…

[Leetcode][第207题][JAVA][课程表][拓扑排序][DFS]

【问题描述】[中等] 【解答思路】 1. 拓扑排序 复杂度分析 HashSet[] 数组 import java.util.HashSet; import java.util.LinkedList; import java.util.Queue;public class Solution {public boolean canFinish(int numCourses, int[][] prerequisites) {if (numCourses &l…

RabbitMQ(1) - win+rabbitMQ

rabbitMQ是一个在AMQP协议标准基础上完整的&#xff0c;可服用的企业消息系统。它遵循Mozilla Public License开源协议&#xff0c;采用 Erlang 实现的工业级的消息队列(MQ)服务器&#xff0c;Rabbit MQ 是建立在Erlang OTP平台上。 1.安装Erlang 所以在安装rabbitMQ之前&…