import java.util.HashMap;
/**
* 面试题35:复杂链表的复制
* 题目:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,
* 另一个特殊指针random指向一个随机节点),
* 请对此链表进行深拷贝,并返回拷贝后的头结点。
* (注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
*
* @author
* @create 2021-05-03 15:14
*/
public class Solution35 {
public static void main(String[] args) {
}
/**
* 方法一:使用map存储原链表的随机指向关系,时间复杂度O(n),空间复杂度O(n)
* @param pHead
* @return
*/
public static RandomListNode Clone(RandomListNode pHead) {
if (pHead == null){
return null;
}
//创建target头结点
RandomListNode target = new RandomListNode(pHead.label);
//获取原链表的头结点
RandomListNode cur = pHead;
//获取新链表的头节点
RandomListNode p = target;
//使用辅助空间,将遍历过的每一个节点都存入map中,存储原节点和新节点
HashMap<RandomListNode, RandomListNode> map = new HashMap<>();
while (pHead != null){
map.put(pHead,new RandomListNode(pHead.label));
pHead = pHead.next;
}
//target作为新链表的表头,移动cur和p来复制链表
while (cur != null){
p.next = map.get(cur.next);
p.random = map.get(cur.random);
cur = cur.next;
p = p.next;
}
return target;
}
/**
* 方法二:将复制节点放在原节点后面,时间复杂度O(n),不使用辅助空间
* @param pHead
* @return
*/
public static RandomListNode CloneTwo(RandomListNode pHead) {
if (pHead == null){
return null;
}
//1、遍历链表,复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;
RandomListNode cur = pHead;
while (cur != null){
RandomListNode node = new RandomListNode(cur.label);
node.next = cur.next;
cur.next = node;
cur = node.next;
}
//2、重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;
cur = pHead;
while (cur != null){
cur.next.random = cur.random == null ? null : cur.random.next;
cur = cur.next.next;
}
//3、拆分链表,将链表拆分为原链表和复制后的链表
cur = pHead;//原链表的表头
RandomListNode pCloneHead = pHead.next;//新链表的表头
while (cur != null){
RandomListNode cloneNode = cur.next;
cur.next = cloneNode.next;
cloneNode.next = cloneNode.next == null ? null : cloneNode.next.next;
cur = cur.next;
}
return pCloneHead;
}
}
class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
【剑指Offer】面试题35:复杂链表的复制
最新推荐文章于 2022-03-25 20:56:10 发布