复制含有随机指针节点的链表
时间:2021-08-11
本文章向大家介绍复制含有随机指针节点的链表,主要包括复制含有随机指针节点的链表使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
【题目】一种特殊的单链表节点类描述如下
class Node{ int value; Node next; Node rand; Node(int val){ value = val; } }
rand指针是单链表节点结构中新增的指针,rand可能指向链表中的任意一个节点,也可能指向null。
给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表的复制,并返回复制的新链表的头节点。
【要求】时间复杂度0(N),额外空间复杂度0(1)
解法:
一、利用额外空间 哈希表
1、新建一个哈希表,以老链表的Node为key,值为对应copy的Node
2、处理next指针
3、处理rand指针
二、不利用额外空间
1、生成克隆节点,放在老链表的下一个,然后克隆节点去窜上老链表的下一个
2、设置rand指针
把1和克隆的1单独拿出来,通过1找出rand指针的指向的Node节点,Node.next就是克隆的Node,让克隆出来的1的rand指针指向克隆出来的Node。依次类推
3、分离新老链表
代码
package Algorithms; /** * @author : zhang * @version : 1.0 * @date : Create in 2021/8/11 * @description : */ import java.util.HashMap; public class CopyListWithRandom { public static class Node { public int value; public Node next; public Node rand; public Node(int data) { this.value = data; } } //笔试 额外空间 哈希表 public static Node copyListWithRand1(Node head) { HashMap<Node, Node> map = new HashMap<Node, Node>(); Node cur = head; //1、循环往map中克隆Node,以老Node为key,value为对应copy的Node while (cur != null) { map.put(cur, new Node(cur.value)); cur = cur.next; } cur = head; //2、处理next指针与rand指针 while (cur != null) { //cur老 map.get(cur) 新 //cur.next为链表中Node的下一个节点, // 找出来作为key,在map中查找的value就是新Node【map.get(cur).next)】的next所要指向的节点 map.get(cur).next = map.get(cur.next); map.get(cur).rand = map.get(cur.rand); cur = cur.next; } return map.get(head); } //面试:不利用额外空间 public static Node copyListWithRand2(Node head) { if (head == null) { return null; } Node cur = head; Node next = null; //1、 copy node and link to every node //例 【1 ->2 】 -> 【1 -> 1' -> 2 -> 2'】 while (cur != null) { next = cur.next; //next保存cur的下一个节点 cur.next = new Node(cur.value); //cur的下一个Node指向新克隆的Node cur.next.next = next; //新克隆的Node的下一个节点指向next cur = next;//cur后移,然后重复以上操作 } cur = head; Node curCopy = null; //2、 set copy node rand while (cur != null) { next = cur.next.next; curCopy = cur.next; curCopy.rand = cur.rand != null ? cur.rand.next : null; cur = next; } Node res = head.next; cur = head; //3、 split while (cur != null) { next = cur.next.next; curCopy = cur.next; cur.next = next; curCopy.next = next != null ? next.next : null; cur = next; } return res; } public static void printRandLinkedList(Node head) { Node cur = head; System.out.print("order: "); while (cur != null) { System.out.print(cur.value + " "); cur = cur.next; } System.out.println(); cur = head; System.out.print("rand: "); while (cur != null) { System.out.print(cur.rand == null ? "- " : cur.rand.value + " "); cur = cur.next; } System.out.println(); } public static void main(String[] args) { Node head = new Node(1); head.next = new Node(2); head.next.next = new Node(3); head.next.next.next = new Node(4); head.next.next.next.next = new Node(5); head.next.next.next.next.next = new Node(6); head.rand = head.next.next.next.next.next; // 1 -> 6 head.next.rand = head.next.next.next.next.next; // 2 -> 6 head.next.next.rand = head.next.next.next.next; // 3 -> 5 head.next.next.next.rand = head.next.next; // 4 -> 3 head.next.next.next.next.rand = null; // 5 -> null head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4 System.out.println("原链表为:"); printRandLinkedList(head); Node res1 = copyListWithRand1(head); System.out.println("【方式1】copy的链表为:"); printRandLinkedList(res1); Node res2 = copyListWithRand2(head); System.out.println("【方式2】copy的链表为:"); printRandLinkedList(res2); System.out.println("原链表为:"); printRandLinkedList(head); } } /** * 原链表为: * order: 1 2 3 4 5 6 * rand: 6 6 5 3 - 4 * 【方式1】copy的链表为: * order: 1 2 3 4 5 6 * rand: 6 6 5 3 - 4 * 【方式2】copy的链表为: * order: 1 2 3 4 5 6 * rand: 6 6 5 3 - 4 * 原链表为: * order: 1 2 3 4 5 6 * rand: 6 6 5 3 - 4 */
原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/15128813.html
- centos7编译安装Redis
- hdu----(5023)A Corrupt Mayor's Performance Art(线段树区间更新以及区间查询)
- Redis单线程架构
- hdu----(4521)小明系列问题——小明序列
- Redis数据结构和内部编码
- Redis全局命令
- nginx使用GeoIP限制国家访问
- shell获取每月最后一天
- 定向转发和重定向实现 <select >下拉表单数据传送
- Python:获取某月第一天和最后一天
- hdu 3635 Dragon Balls (带权并查集)
- 沃趣QFusion vs MGR、MGC面面观
- Redis的配置、启动、操作及关闭
- 剖析Go编写的Socket服务器模块解耦及基础模块的设计
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 刺激!一行代码即可导出所有浏览记录
- 你不知道的 node 爬虫原来这么简单
- 带货直播系统源码中,商品详情页是如何搭建起来的
- 基于飞桨复现CVPR 2020 GhostNet的全程解析
- 【即时通信IM】红包消息如何构建?
- YOLOv4损失函数全面解析
- Pandas进阶修炼120题,给你深度和广度的船新体验
- 5万字、97 张图总结操作系统核心知识点
- C++核心准则CP.100:不要使用无锁编程方式,除非绝对必要
- 神了,Excel的这个操作我今天才知道
- DataFrame(7):DataFrame运算——逻辑运算
- 高性能网关设计实践
- LASSO回归姊妹篇:R语言实现岭回归分析
- 学了这个,三歪再也不想写各种setter了
- 使用 GitLab CI 与 Argo CD 进行 GitOps 实践