随机指针链表深复制
来源:互联网 发布:swift model数组 编辑:程序博客网 时间:2024/06/03 19:06
题目描述[微软苏州]
一条带随机指针的链表,对于每个节点,除了next
指针指向下一个节点以外,还带一个randNext
指针指向链表中任何一个节点或空。求对这个链表进行深复制,即复制出的链表和原来链表具有完全相同的结构,但是与原链表完全无关。
分析1
此题难点在于新建链表节点的randNext
不能立即在新链表中找到指向,如果要记录randNext
指向节点相对于自身的位置,那么每个节点都需要有一个遍历计数过程,时间复杂度为randNext
指向的节点就成为了关键步骤。
使用链表的问题在于查找过程需要遍历,从而导致了效率低下,所以可以想到使用哈希来快速查找所需要的节点。这里HashMap
记录旧节点和新节点之间的映射关系,一旦得到了一个旧节点,就可以立刻找到新节点,查找的复杂度为HashMap
,一次复制链接。
代码1
static Node copyWithHash(Node headNode) { Map<Node, Node> map = new HashMap<>(); Node oldNode = headNode; // 建立新节点与原节点的映射 while (oldNode != null) { map.put(oldNode, new Node(oldNode.data + 100));// 测试 oldNode = oldNode.next; } oldNode = headNode; Node newHeadNode = null; Node newNode = null; // 利用映射将旧链接关系复制到新链接关系 while (oldNode != null) { newNode = map.get(oldNode); newNode.next = map.get(oldNode.next); newNode.randNext = map.get(oldNode.randNext);// get(null)仍返回null if (newHeadNode == null) newHeadNode = newNode; oldNode = oldNode.next; } return newHeadNode;}
分析2
使用HashMap
的空间复杂度为next
就可以找到新节点了。只是复制过程复杂一些,需要三次遍历才可以:第一次插入新节点到原链表中,即newNode.next = oldNode.next; oldNode.next = newNode
,第二次复制链接关系,即newNode.randNext = oldNode.randNext.next
,最后一次从原链表分离出新链表,即oldNode.next = newNode.next; newNode.next = newNode.next.next
。
代码2
static Node copyInsertion(Node headNode) { // 第一遍将新节点链接到旧节点next后,并链接到下一个旧节点 Node oldNode = headNode; while (oldNode != null) { Node newNode = new Node(oldNode.data + 100);// 测试 newNode.next = oldNode.next; oldNode.next = newNode; oldNode = newNode.next; } // 第二遍将旧节点randNext链接关系复制到新节点上 oldNode = headNode; while (oldNode != null) { Node newNode = oldNode.next; if (oldNode.randNext != null){ newNode.randNext = oldNode.randNext.next; } oldNode = newNode.next; } // 第三遍将新节点与旧节点分离开 Node newHeadNode = null; oldNode = headNode; while (oldNode != null) { Node newNode = oldNode.next; oldNode.next = newNode.next; oldNode = oldNode.next; if (oldNode != null) newNode.next = oldNode.next; if (newHeadNode == null) newHeadNode = newNode; } return newHeadNode;}
测试
import java.util.HashMap;import java.util.Map;import java.util.Random;public class RandLinked { static class Node { int data; Node next = null, randNext = null; Node(int data) { this.data = data; } } static Node buildRandLinked(int[] data) { int length = data.length; Map<Integer, Node> map = new HashMap<>(length); for (int i : data) { map.put(i, new Node(i)); } int[] randIndex = new int[length]; Random random = new Random(); for (int i = 0; i < length; i++) { randIndex[i] = random.nextInt(length); } Node headNode = map.get(data[0]); Node tmpNode = null; for (int i = 0; i < length - 1; i++) { tmpNode = map.get(data[i]); tmpNode.next = map.get(data[i + 1]); if (randIndex[i] % 4 == 0) tmpNode.randNext = null; else tmpNode.randNext = map.get(data[randIndex[i]]); } return headNode; } static void printRandLinked(Node headNode) { Node tmpNode = headNode; while (tmpNode != null) { System.out.print(tmpNode.data + " -> "); System.out.println(tmpNode.randNext == null ? null : tmpNode.randNext.data); tmpNode = tmpNode.next; } } public static void main(String[] args) { Node headNode = buildRandLinked(new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); printRandLinked(headNode); System.out.println("-----------"); printRandLinked(copyInsertion(headNode)); }} /* result0 -> null1 -> 22 -> 33 -> 94 -> 65 -> null6 -> 77 -> 98 -> 69 -> null-----------100 -> null101 -> 102102 -> 103103 -> 109104 -> 106105 -> null106 -> 107107 -> 109108 -> 106109 -> null*/
0 0
- 随机指针链表深复制
- 复制带随机指针的链表
- 复制带随机指针的链表
- 复制带随机指针的链表
- 复制带随机指针的链表
- 复制带随机指针的链表
- 复制带随机指针的链表
- 复制带随机指针的链表
- 复制带有随机指针的链表
- 复制含有随机指针的链表
- 带随机指针的链表复制问题
- M1: 复制带随机指针的链表
- 复制一个带随机指针的链表
- LintCode复制带随机指针的链表
- 复杂链表的复制(结点包含随机指针)
- 题目:复制带随机指针的链表
- 复制含有随机指针节点的链表
- LintCode(105) 复制带随机指针的链表
- 结构体初始化
- Windows安装TensorFlow
- HAProxy与负载均衡概念介绍
- Fiddler 教程
- css3 pointer-events:none 允许点击穿透
- 随机指针链表深复制
- typescript基础类型
- 产品策划流程体系、工具
- Servlet入门_Three之Listener
- LeetCode24. Swap Nodes in Pairs
- PHP批量生成密码功能
- excel文件下载实现方法
- Spring基础
- 理解OAuth 2.0