24. 复杂链表的复制

题目

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

public class RandomListNode {
	int val;
	RandomListNode next = null;
	RandomListNode random = null;
	public RandomListNode(int  val) {
		this.val = val;
	}
}

思路1

当我们访问一个结点时可能它的随机指针指向的结点还没有访问过,结点还没有创建;因为在我们还没有完全遍历一边链表的时候没有办法知道所有结点的地址。

先按照复制一个正常链表的方式复制,复制的时候把复制的结点做一个HashMap,以旧结点为key新节点为value。这么做的目的是为了第二遍扫描的时候我们按照这个哈希表把结点的随机指针接上。总共要进行两次扫描,所以时间复杂度是O(2*n)=O(n)。空间上需要一个哈希表来做结点的映射,所以空间复杂度也是O(n)

public RandomListNode copyRandomList1(RandomListNode head){
		if(head == null) return head;
		HashMap<RandomListNode,RandomListNode> map = new HashMap<RandomListNode,RandomListNode>();
		//创建新链表
		RandomListNode newHead = new RandomListNode(head.val);  
		//新节点和旧节点放到map里面
		map.put(head,newHead);  
		RandomListNode pre = newHead;  
		RandomListNode node = head.next;  
		while(node!=null) {  
			//创建新节点,并把旧节点和新节点放到map里面
			RandomListNode newNode = new RandomListNode(node.val);  
			map.put(node,newNode);  
			pre.next = newNode;  
			pre = newNode;  
			node = node.next;  
		}  
		node = head;  
		RandomListNode copyNode = newHead;  
		while(node!=null) {  
			//遍历旧链表,对应map拿到旧节点的随机指针然后赋给新节点的随机指针
			copyNode.random = map.get(node.random);  
			copyNode = copyNode.next;  
			node = node.next;  
		}  
		return newHead;  
	}

思路2

如果不用map这个数据结构该怎么搞呢?还是要解决原结点和对应新结点之间的映射关系:

  • 每新建一个结点就把该结点插入到原链表对应的原结点后;
  • 上一步全部完成后,遍历原链表(2倍长度了),由于原结点和新结点之间是相邻的,因此只要p->next就可以通过原结点找到对应的新结点,这样就解决了这个映射关系,这一步确定随机指针;
  • 最后一步就是把加长后的链表拆分出来,这样即保证创建了新链表,也保证了原链表没有被破坏。
public RandomListNode CopyRandomList2(RandomListNode head){
		if(head == null)  return head;  
		RandomListNode node = head;  
		while(node!=null)  {  
			RandomListNode newNode = new RandomListNode(node.val);  
			newNode.next = node.next;  
			node.next = newNode;  
			node = newNode.next;  
		}  
		node = head;  
		while(node!=null)  {  
			if(node.random != null)  
				//这里node.random.next指向的是新节点,如果直接node.random就是连到原链表上了
				node.next.random = node.random.next;  
			node = node.next.next;  
		}  
		RandomListNode newHead = head.next;  
		node = head;  
		while(node != null)  {  
			RandomListNode newNode = node.next;  
			node.next = newNode.next;  
			if(newNode.next!=null)  
				newNode.next = newNode.next.next;  
				node = node.next;  
		}  
		return newHead; 
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值