剑指offer:复杂链表的复制
作者:互联网
剑指offer:复杂链表的复制
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
输入描述
输入
返回
解题思路
一、暴力解法
- 复制正常的链表指针域
这个操作比较简单,因为链表的下一个指针为形成一个串的,我们从头开始即可遍历所有的结点 - 复制随机的指针域
这个操作有点麻烦,由于指针是随机指向的,因此无法通过一趟遍历来实现,这里我们采用暴力的方式,
由于指针的位置是一一对应的,我们查找到原来的随机指针域在新链表中对应位置(O(N)O(N)),而我们遍历一遍将所有的随机指针都复制则需要O(N2),空间复杂度O(1)
public RandomListNode Clone(RandomListNode pHead){
if(pHead == null){ //原链表为空
return null;
}
RandomListNode head = pHead;
RandomListNode newhead = null , curhead = null; //新链表头节点、当前节点
while(head != null){
RandomListNode node = new RandomListNode(head.label);
head = head.next; //原链表移动
if(curhead == null){ //新链表当前节点为空
newhead = node; //头节点赋值
}else{
curhead.next = node;//将新节点连接到新链表中
}
curhead = node; //当前节点移动
}
head = pHead; RandomListNode cur = newhead;
while(head != null && cur != null){
RandomListNode oldRand = head.random; //旧节点的随机节点
RandomListNode newRand = null;
newRand = findRand(pHead,newhead,oldRand); //找到新节点的随机节点在新链表的位置
cur.random = newRand; //赋值随机节点
cur = cur.next; //旧链表移动
head = head.next; //新链表移动
}
return newhead;
}
//查找随机节点在新链表的位置
private RandomListNode findRand(RandomListNode oldhead,RandomListNode newhead,RandomListNode oldRand){
RandomListNode old = oldhead;
RandomListNode node = newhead;
while(old != null && node != null){ //遍历新旧链表
if(old == oldRand){ //找到随机节点在旧链表的位置
return node;
}
old = old.next;
node = node.next;
}
return null;
}
二、使用HashMap优化
复制正常的链表指针域
这个操作比较简单,因为链表的下一个指针为形成一个串的,我们从头开始即可遍历所有的结点。
使用HashMap存储
old.node
与new.node
,因为新旧链表的node是一对一关系,所以使用get(old.node.random)
可以获得new.node.random
,然后赋值给newNode即可。时间复杂度O(N),时间复杂度O(N)
public RandomListNode Clone(RandomListNode pHead){
if(pHead == null) return null;
RandomListNode head = pHead;
RandomListNode newHead = null, curNode = null;
HashMap<RandomListNode,RandomListNode> map = new HashMap<>(); //创建新map
while(head != null){
RandomListNode node = new RandomListNode(head.label);
map.put(head,node); //将新旧节点加入map
if(curNode == null){
newHead = node;
}else{
curNode.next = node;
}
head = head.next;
curNode = node;
}
head = pHead; curNode = newHead;
while(head != null && curNode != null){
//根据旧节点的random获得新节点的random
curNode.random = (RandomListNode)map.get(head.random);
curNode = curNode.next;
head = head.next;
}
return newHead;
}
三、复制拆分
空间复杂度O(1),时间复杂度O(N)
public RandomListNode Clone(RandomListNode pHead){
if(pHead == null) return null;
RandomListNode head = pHead;
while(head != null){ //复制新节点并连接到旧链表
RandomListNode node = new RandomListNode(head.label);
node.next = head.next;
head.next = node;
head = node.next;
}
head = pHead;
while(head != null){ //根据旧节点的random赋值新节点的random
head.next.random = head.random == null ? null : head.random.next;
head = head.next.next;
}
head = pHead;
RandomListNode check = head.next;
while(head != null){ //拆分
RandomListNode node = head.next; //新链表头节点
head.next = node.next; //将旧节点重新连接
node.next = node.next == null ? null : node.next.next; //将新节点拆分出来
head = head.next;
}
return check;
}
标签:node,head,RandomListNode,offer,next,链表,复制,null 来源: https://www.cnblogs.com/le-le/p/12458496.html