这个刚开始想的是先顺着next遍历一遍链表,把所有元素都存在动态数组里。然后再遍历各个结点的random,把random都连上。
但提交后发现,next有可能无法遍历完所有的结点,比如有的结点的random连接的是并没有在next链中出现的结点。
1->2->3->4->null 5->6
如果1的random是5,那光靠next是遍历不到的。
同理,先遍历random也会丢失元素。
怎么先遍历完所有元素?纠结了我半天。然后突然想明白了:其实,不管是next,还是random,只是名字不同而已,他们只是代表了两条从pHead开始的链表。你先遍历next,那random是跳着连的;但你要先遍历random,其实random是连续的,next是跳着的。
所以,这就是个简单的路径选择问题,或者说,二叉树的左右树。只不过遍历的中途可能遍历到已经遍历过的结点,那做个标记就行了。
标记flag用int,0代表第一次来,啥没做过;1代表next已经遍历过了;2代表next,random都遍历过了,结束吧!
既然是二叉树,自然是用递归。代码如下:
import java.util.*;
public class Solution {
public static ArrayList<RandomListNode> alrs1; //原始节点队列
public static ArrayList<RandomListNode> alrs2; //复制节点队列
public static ArrayList<Integer> flag; //路径选择标志
public RandomListNode Clone(RandomListNode pHead)
{
if(pHead==null){
return pHead;
}
alrs1=new ArrayList<RandomListNode>();
alrs2=new ArrayList<RandomListNode>();
flag=new ArrayList<Integer>();
alrs1.add(pHead);
RandomListNode p=new RandomListNode(pHead.label);
RandomListNode first=p;
alrs2.add(p);
flag.add(1);
bianli(pHead.next,p);
if(flag.get(0)==1){
bianli(pHead.random,p);
}
return first;
}
public void bianli(RandomListNode rn,RandomListNode pre){
if(rn==null){
return;
}
int loc=alrs1.indexOf(rn);
RandomListNode buf;
if(loc==-1){
alrs1.add(rn);
buf=new RandomListNode(rn.label);
alrs2.add(buf);
int loc2=alrs2.indexOf(pre);
if(flag.get(loc2)==2) {
pre.random=buf;
}else {
pre.next=buf;
}
pre=buf;
flag.add(0);
loc=flag.size()-1;
}else{
buf=alrs2.get(loc);
pre.random=buf;
pre=buf;
}
if(flag.get(loc)==0){
flag.set(loc,1);
bianli(rn.next,buf);
if(flag.get(loc)==1){
bianli(rn.random,buf);
}
}else if(flag.get(loc)==1){
flag.set(loc,2);
bianli(rn.random,buf);
}else{
return;
}
}
}


京公网安备 11010502036488号