题目:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
解题思路:
首先有三种解法:
第一种就是中规中矩的解法,首先复制next指针的节点,之后再复制random指针的节点,这种解法的缺点是时间复杂度太高,O(n^2).
第二种思路就是以空间换时间,设置一个HashMap用来存储每一个链表的节点,<key, value> 分别为原链表节点、新链表节点,复制的过程还是分两步完成,第一步就是顺着next依次复制,第二步就是复制random指针,如果原链表random指针不为空则从map中取出来,然后设置对应新链表的节点,这样空间复杂度为O(n), 时间复杂度为O(n)。
第三种思路就是在不用辅助空间的情况下实现O(n)的解法,大体步骤还是第二种思路那样两步,不同的是第一步顺着next走的时候我们复制出来的新节点紧接着插入对应的旧节点后面,第二步再复制random指针。最后一步就是将链表拆分成新链表和旧链表两个部分。
代码:
第二种思路代码:
public RandomListNode Clone(RandomListNode pHead) {
if (pHead == null) {
return null;
}
RandomListNode p = pHead;
RandomListNode head = new RandomListNode(-1);
RandomListNode q = head;
HashMap<RandomListNode, RandomListNode> hash = new HashMap<>();
while (p != null) {
RandomListNode tmp = new RandomListNode(p.label);
hash.put(p, tmp);
q.next = tmp;
q = q.next;
p = p.next;
}
//q = head.next;
p = pHead;
while (p != null) {
if (p.random != null) {
RandomListNode value = hash.get(p);
RandomListNode random = hash.get(p.random);
value.random = random;
}
p = p.next;
}
return head.next;
}
第三种思路代码:
public static RandomListNode copyRandomList(RandomListNode pHead) {
if (pHead == null) {
return null;
}
//复制并且插入
RandomListNode p = pHead;
while (p != null) {
RandomListNode tmp = new RandomListNode(p.label);
tmp.next = p.next;
p.next = tmp;
p = tmp.next;
}
//复制random指针
p = pHead;
while (p != null) {
if (p.random != null) {
p.next.random = p.random.next;
}
p = p.next.next;
}
//拆分链表
RandomListNode head = pHead.next;
RandomListNode q = head;
p = pHead;
//这个部分需要注意一下
while (q.next != null) {
p.next = q.next;
p = p.next;
q.next = p.next;
q = q.next;
}
p.next = null; //最后将原来链表的尾部设置为null
return head;
}
---------------------
作者:will_duan
来源:CSDN
原文:https://blog.csdn.net/willduan1/article/details/53352759
版权声明:本文为博主原创文章,转载请附上博文链接!