分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程
package live.every.day.ProgrammingDesign.CodingInterviewGuide.List;
/**
* 复制含有随机指针节点的链表
*
* 【题目】
* 一种特殊的链表节点类描述如下:
* 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)内完成原问题要实现的函数。
*
* 【难度】
* 中等
*
* 【解法】
* 接下来介绍进阶解法,进阶解法不使用哈希表来保存对应关系,而只用有限的几个变量完成所有的功能。具体过程如下:
* 1、首先从左到右遍历链表,对每个节点cur都复制生成相应的副本节点copy,然后把copy放在cur和下一个要遍历节点的中间。
* 2、再从左到右遍历链表,在遍历时设置每一个副本节点的rand指针。
* 3、步骤2完成后,节点1、2、3、...之间的rand关系没有任何变化,节点1'、2'、3'、...之间的rand关系也被正确设置了,此
* 时所有的节点与副本节点串在一起,将其分离出来即可。
* 4、将1'节点作为结果返回即可。
* 进阶解法考查的依然是利用有限几个变量完成链表调整的代码实现能力。具体过程请参看如下代码中的copyListWithRand2方法。
*
* @author Created by LiveEveryDay
*/
public class CopyRandomPointerNodeList2 {
public static class Node {
public int data;
public Node next;
public Node rand;
public Node(int data) {
this.data = data;
}
}
public static Node copyListWithRand2(Node head) {
if (head == null) {
return null;
}
Node cur = head;
Node next = null;
// 复制并链接每一个节点
while (cur != null) {
next = cur.next;
cur.next = new Node(cur.data);
cur.next.next = next;
cur = next;
}
cur = head;
Node curCopy = null;
// 设置复制节点的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;
// 拆分
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 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 = copyListWithRand2(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
*/