Copy List with Random Pointer

题目: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;
	}
}


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值