标签:copy list with rando 深拷贝 复杂链表复制
题目:https://oj.leetcode.com/problems/copy-list-with-random-pointer/
题目给出了一个特殊的单链表。链表的每一个节点多了个指针域: random. 随机只向链表的某一个 node。 题目要求我们给出这个链表的一个 deep copy。
1. Shallow copy
拷贝时仅仅复制的是指针或者引用, 也就是说 数据仅存在一份。当然,得到效率的同时,存在的问题就是,如果原来的数据改变了,复制后的对象也改变了,因为仅仅存在一份数据!!!
Note: 其实是出于效率的考虑,在某些场合,并不需要多份数据时,可以采用 shallow copy。
2. deep copy
拷贝时不仅复制指针或者引用,把指向的数据重新复制一份,如果原来的数据改变了,复制后的对象不会改变,因为它们拥有的是两份不同的数据。
3. Lazy copy
这是一种上述两种策略的组合。又称为 copy-on-write.
最初复制时,采用效率更高的 shallow copy, 同时用一个计数器 counter 记录当前share数据的对象数目。
当需要对数据进行修改时,根据 counter, 采用 deep-copy,
也就是当需要 deep-copy 时,才调用比较费时的 deep-copy.
回到这道题目我们需要怎么做?
其实这道题在剑指offer上出现过,我也实现过,今天再次实现比以前实现做的更好一些。以前实现:http://blog.csdn.net/huruzun/article/details/22292451
思路: Step 1: 首先指向在原链表的每个节点后面,复制一个新的节点,原链表长度变为 2 倍
random 指针指向的是 原链表节点 random 指针指向的节点的后面的那个节点
Step 2: 将链表拆成两个链表 。
实现一定注意一点:分离两个链表,这里特别注意不能改动原先链表状态,否则无法AC。
public class Solution { public RandomListNode copyRandomList(RandomListNode head) { if (head == null) { return null; } RandomListNode p = head; RandomListNode next = null; // 先完成copy while(p!=null){ next = p.next; RandomListNode node = new RandomListNode(p.label); node.next = next; p.next = node; p = next; } p = head; RandomListNode q = p.next; // 复制random while(p!=null){ if(p.random!=null){ q.random = p.random.next; } p = p.next.next; // q移动两步指针则需要先进行判断 if(p!=null){ q = q.next.next; } } RandomListNode newHead = head.next; RandomListNode pHead = head; RandomListNode qHead = newHead; // 分离两个链表,这里特别注意不能改动原先链表状态。 while(pHead!=null ){ pHead.next = qHead.next; if(qHead.next!=null){ qHead.next = qHead.next.next; } pHead = pHead.next; if(pHead!=null){ qHead = qHead.next; } } return newHead; } }
标签:copy list with rando 深拷贝 复杂链表复制
原文地址:http://blog.csdn.net/huruzun/article/details/39053795