链表:常见面试题-拷贝特殊链表

news/2024/12/21 22:01:24/

题目:

一种特殊的单链表节点类描述如下:

class Node {

        int value;

        Node next;

        Node rand;

        Node(int val) {value = val}

}

rand指针是单链表节点结构中新增的指针,rand可能指向链表中的任意一个节点(包括自己),也可能指向null.

给定一个由Node节点类型组成的无环单链表的头结点head,请实现一个函数完成复制这个链表,并返回新链表的头结点。

要求:时间复杂度O(N),额外空间复杂度O(1)

思路:这个题仍然有两种解法:利用额外容器或者使用有限几个变量,具体思路:

(1)使用额外的容器,使用一个HashMap,把当前链表的每一个Node作为key装入HashMap,value是它的拷贝节点,都装完之后依次取出每一个Node,把value(拷贝节点)的next和random分别指向HashMap中取出的以当前节点的next和random为key的拷贝节点,没有

(2)不使用额外的容器,只使用有限几个变量,先遍历链表,依次拷贝Node然后把拷贝节点放在当前当前节点和原来的next中间。 然后依次遍历链表,设置各个拷贝节点的random指针指向。最后把两个链表进行拆分.

第一种方法面试没有分且笔试的空间复杂度为O(N),笔试也过不了,这里我们不做介绍,有兴趣的可以自己写写玩。

第二种方法的拆分示意图:

对应的代码如下:

package dataStructure.linkedList.practice;import dataStructure.linkedList.ListNodeWithRandom;public class CopyLinkedListWithRandom {public static ListNodeWithRandom copyLinkedList(ListNodeWithRandom head) {if(head == null) return head;ListNodeWithRandom cur = head;ListNodeWithRandom next = null;//把每个节点复制一个放在当前节点和当前节点的next之间,最后一个copy放在当前节点和null之间//例如1->2->3变成1->11->2->22->3->33while(cur != null) {next = cur.next;cur.next = new ListNodeWithRandom(cur.val, cur.name+"'");cur.next.next = next;cur = next;}cur = head;//设置random指针while(cur != null) {//取到当前Node的random指针ListNodeWithRandom random = cur.random;//当前random如果为空,那拷贝节点的random也应该为空//如果当前random不为空,则random的下一个(原链表中random的拷贝)就是拷贝节点的randomcur.next.random = random == null? null : random.next;//cur.next.next是原链表中cur的下一个节点cur = cur.next.next;}//分离原链表和拷贝链表//1->11->2->22->3->33 分离为1->2->3和11->22->33cur = head;ListNodeWithRandom newHead = null;while(cur != null) {//取到cur的拷贝节点ListNodeWithRandom curCopy = cur.next;//如果当前节点是头节点,则它的拷贝就是新链表的头if(newHead == null) {newHead = curCopy;}//cur的下一个节点就是curCopy的下一个节点cur.next = curCopy.next;//curCopy的next取决于cur.next是否为空,如果为空,则它的next也应该为空//如果不为空,根据规律我们应该取cur.next的下一个节点(cur.next的拷贝)curCopy.next = cur.next == null? null : cur.next.next;//这个时候cur.next已经是cur的原链表的下一个节点了cur = cur.next;}return newHead;}public static void main(String[] args) {ListNodeWithRandom n1 = new ListNodeWithRandom(1, "1");ListNodeWithRandom n2 = new ListNodeWithRandom(2,"2");ListNodeWithRandom n3 = new ListNodeWithRandom(3, "3");n1.next = n2;n2.next = n3;n1.random = n3;n2.random = n1;n3.random = n2;ListNodeWithRandom newHead = copyLinkedList(n1);while(newHead != null) {if(newHead.next != null) {System.out.print(newHead + " ->");} else {System.out.print(newHead);}newHead = newHead.next;}}
}

运行结果:

{val=1, random=3', name='1''} ->{val=2, random=1', name='2''} ->{val=3, random=2', name='3''}

粗略代码,难免出错,欢迎批评指正


http://www.ppmy.cn/news/450698.html

相关文章

盐城市公交路线及时刻表

盐城B支1路公交车运营时间:6:00--20:30 单程票价:1元 途经道路:城西公交回车场-西环路-建军西路-太平路-大庆路-解放路-青年路-亭湖大道-生物工程学校城西公交回车场- 蟒蛇河大桥(北) - 市一院 - 泰山庙 - 市房产交易市场 - 太平人…

哈希表--day2--(leetcode242/leetcode383/leetcode49/leetcode438)

文章目录 leetcode242.有效的字母异位词基本思路AC-code leetcode383. 赎金信基本思路AC-code leetcode49.字母异位词分组基本思路AC-code leetcode438.找到字符串中所有字母异位词基本思路AC-code leetcode242.有效的字母异位词 链接 基本思路 思路实际上很简单&#xff0c…

Java三大器小结

filter实例/filter实例/监听器实例过滤和拦截区别/Listener实例/Listener实例

Servlet 三大器

文章目录 脑图 英文博客

大器人生

大器人生 古希腊著名政治家伯利克里任雅典首席官时,由于进行了一系列改革,反对者甚众,有人当面辱骂,但他从不动怒。一天傍晚,一个市民还闯进伯利克里的屋子,一进门就对着他骂个不停。但伯利克里只是静静地坐…

python三大_Python之三大器

一、装饰器 闭包函数 闭:指的是定义在函数内部的函数 比如手机是闭包函数(内层函数),被手机包装盒 (外层函数) 包裹起来, 手机可以使用包装盒中的东西,内层函数可以引用外层函数的名字。 闭包函数:定义在函数内部的函数…

高频谐振功放大器

高频谐振功率放大器的主要特点是:输出功率足够大、效率高、非线性失真小及频带宽度 影响放大器输出功率的主要因素 功率管本身的集电极最大允许电流、反向击穿电压和最大允许耗散功率 提高放大器输出功率的方法 高频输出功率是高频放大器在输入信号的控制下&#…

java中三web_Java Web中的三大器

java Web中的三大器 先看一张图,对三大器的的作用范围有一个大致的了解 java三大器.PNG 监听器(listener) 作用 1.首先监听器的作用的范围最长。 2.监听器的监听事件源分别为ServletContext,HttpSession和ServletRequest这三个域对象。 因此,…