分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程
package live.every.day.ProgrammingDesign.CodingInterviewGuide.List;
import java.util.HashMap;
/**
* 复制含有随机指针节点的链表
*
* 【题目】
* 一种特殊的链表节点类描述如下:
* public class Node{
* public int data;
* public Node next;
* public Node rand;
* public Node (int data){
* this.data=data;
* }
* }
* Node类中的data是节点数据,next指针和正常单链表中next指针的意义一样,都指向下一个节点,rand指针是Node类中新增的指
* 针,这个指针可能指向链表中的任意一个节点,也可能指向null。
* 给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表中所有结构的复制,并返回复制的新链表的
* 头节点。
*
* 【难度】
* 中等
*
* 【解法】
* 首先介绍普通解法,普通解法可以做到时间复杂度为O(N),额外空间复杂度为O(N),需要使用到哈希表(HashMap)结构。具体过程
* 如下:
* 1、首先从左到右遍历链表,对每个节点都复制生成相应的副本节点,然后将对应关系放入哈希表map中。步骤1完成后,原链表没有
* 任何变化,每一个副本节点的next和rand指针都指向null。
* 2、再从左到右遍历链表,此时就可以设置每一个副本节点的next和rand指针。
* 3、将第1个副本节点作为结果返回即可。
* 哈希表增删改查的操作时间复杂度都是O(1),普通方法一共只遍历链表两遍,所以普通解法的时间复杂度为O(N),因为使用了哈希表
* 来保存原节点与副本节点的对应关系,所以额外空间复杂度为O(N)。
* 具体过程请参看如下代码中的copyListWithRand1方法。
*
* @author Created by LiveEveryDay
*/
public class CopyRandomPointerNodeList1 {
public static class Node {
public int data;
public Node next;
public Node rand;
public Node(int data) {
this.data = data;
}
}
public static Node copyListWithRand1(Node head) {
HashMap<Node, Node> map = new HashMap<>();
Node cur = head;
while (cur != null) {
map.put(cur, new Node(cur.data));
cur = cur.next;
}
cur = head;
while (cur != null) {
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 void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
node1.next = node2;
node2.next = node3;
node3.next = null;
node1.rand = node3;
node2.rand = node2;
node3.rand = node1;
Node head = copyListWithRand1(node1);
Node cur = head;
while (cur != null) {
System.out.printf("%d ", cur.data);
cur = cur.next;
}
System.out.println();
cur = head;
while (cur != null) {
System.out.printf("%d ", cur.rand.data);
cur = cur.next;
}
}
}
// ------ Output ------
/*
1 2 3
3 2 1
*/