算法总结之 复制含有随机指针节点的链表
一种特殊的链表节点类描述如下:
public class Node{
public int value;
public Node next;
public Node rand;
public Node(int data){
this.value = data
}
}
rand指针是Node类中的新增的指针,这个指针可能指向链表中任意的一个节点,也可能指向null
首先介绍普通解法:
使用哈希表
首先从左到右遍历链表,对每个节点都复制生成相应的副本节点
key 1 value 1`
package TT; import java.util.HashMap; public class Test95 { public class Node{ public int value; public Node next; public Node rand; public Node(int data){ this.value=data; } } public Node copyListWithRand1(Node head){ HashMap<Node, Node> map=new HashMap<Node, Node>(); Node cur=head; while(cur != null){ map.put(cur, new Node(cur.value)); 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); } }
介绍进阶做法:
不适用哈希表来保存对应关系,只用有限的几个变量完成所有的功能。
1、首先从左到右遍历链表,对每个节点cur都复制生成相应的副本节点copy,然后把copy放在cur放在cur和下一个要遍历节点的中间
2、再从左到右遍历链表,在遍历时设置每一个副本节点的rand指针
这样: 每个节点的副本节点都在自己的后一个,所以此时通过next就可以找到 以这种方式可以设置每一个副本节点的rand指针
然后将其分离
package TT; public class Test96 { public class Node{ public int value; public Node next; public Node rand; public Node(int data){ this.value=data; } } public Node copyListWidthRand2(Node head){ if(head==null){ return null; } Node cur= head; Node next=null; while(cur!=null){ next=cur.next; cur.next=new Node(cur.value); cur.next.next=next; cur=next; } cur=head; Node curCopy = null; 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; } }