样本:
输入3360 { 1,2,3,4,5,3,5,#,2,#}
输出: { 1,2,3,4,5,3,5,#,2,#}
将分析:链表分为两部分,前半部分{1、2、3、4、5}为ListNode,后半部分{3、5、#、2、#}为随机指针场表示。
上例的前半部分可以表示链表为的ListNode:1-2-3-4-5
后半段、3、5、#、2、#分别是
的位置是3,2的位置是5,3的位置是空的,4的位置是2,5的位置是空的
下图:
第一种解决方案是使用辅助工具,使用map在第一个循环中遍历链表,并将每个节点和节点的副本值作为key和值放入map中。 第二次遍历链表,将每个节点作为密钥查询到map,获取当前节点的random,并将其复制到当前复制节点的random指针。 代码如下
publicrandomlistnodefirstclone (randomlistnodephead )。
if (空值==头) {
返回空值;
}
HashMapRandomListNode,random listnode map=新hashmap (;
randomlistnoderandomlistnode=newrandomlistnode (phead.label );
随机列表头=头;
randomlistnodeclonehead=random列表节点;
地图(头,克隆头);
威尔(空的!=head.next ) {
clone head.next=newrandomlistnode (head.next.label );
head=head.next;
克隆头=克隆头.下一个;
地图(头,克隆头);
}
头=头;
克隆头=随机列表;
威尔(空的!=克隆头) {
克隆头.随机=地图.获取(头随机);
head=head.next;
克隆头=克隆头.下一个;
}
返回随机列表节点;
}第二种解法简称双重节点解法,顾名思义,在复制节点时,将复制节点放在当前节点的后面,复制节点random就是当前节点random。 如果这样操作,则各节点存在双重部分,结果将链表分割为奇数或偶数即可。 结合代码画张图给大家,方便大家,方便自己加强理解。 代码如下
威尔(空的!=head ) {
randomlistnodenode=newrandomlistnode (头.标签);
节点.下一个=头部.下一个;
head.next=节点;
head=node.next;
{1}执行上述代码后,如下图所示
威尔(空的!=头空值!=head.next ) {
if (空值!=head.random ) {
head.next.random=head.random.next;
}
//每个节点后面都有一个复制节点,因此需要跳两个阶段
head=head.next.next;
{1}执行上述代码后,如下图所示
威尔(空的!=头空值!=head.next ) {
head.next=head.next.next;
if (空值==head.next ) {
result.next=空;
}else {
result.next=head.next.next;下一个;
}
结果=结果.下一个;
head=head.next;
}
此代码分割处理后的链表,如下图所示
完整的代码如下
publicrandomlistnodesecondclone (randomlistnodephead )。
if (空值==头) {
返回空值;
}
随机列表头=头;
威尔(空的!=head ) {
randomlistnodenode=newrandomlistnode (头.标签);
节点.下一个=头部.下一个;
head.next=节点;
head=node.next;
}
头=头;
威尔(空的!=头空值!=head.next ) {
if (空值!=head.random ) {
head.next.random=head.random.next;
}
//每个节点后面都有一个复制节点,因此需要跳两个阶段
head=head.next.next;
}
randomlistnoderesulthead=phead.next;
头=头;
randomlistnoderesult=结果头;
//分割链表
威尔(空的!=头空值!=head.next ) {
head.next=head.next.next;
if (空值==head.next ) {
result.next=空;
}else {
result.next=head.next.next;下一个;
}
结果=结果.下一个;
head=head.next;
}
返回结果头;
}