Copy List with Random Pointer复制带随机指针的链表

复制带随机指针的链表

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的深度拷贝。 

这里参考了博文:

https://www.cnblogs.com/TenosDoIt/p/3387000.html(图画的很赞,这里借用了)

https://blog.csdn.net/sun20082567/article/details/36198817(图画的也很赞)

这道题由于链表带随机指针,如果每次遍历都去找每个节点的random指针,那么时间复杂度为O(n),如下图所示:


黑色表示random指针,蓝色表示next指针,未标出表示random指针为nullptr

首先通过原链表构建1'->2'->3'->4',然后对节点1',应该把1'的指针指向3',但是我们怎么得到1'->3'的映射关系呢?我们只有1->3的映射关系,所以直观的想法便是通过计数器来保存每一个节点的random指针是第几个节点,通过next遍历得到,对每一个节点都需要遍历一次原链表,时间复杂度是O(n^2),肯定time limited。所以需要换种思想:

算法一

由上述的提示,如果我们能找到原链表和新链表的映射关系,便可以直接构造新链表的random指针,所以我们需要一个map,

如下图所示:


map的映射关系为key:old_node,value:new_node,更新规则如下公式:

mapper[head_tmp] = new_head_tmp;

然后寻找random指针时用以下公式:

new_head_tmp->random = mapper[head_tmp->random];
代码如下,时间复杂度(O(n)),空间复杂度(O(n)):
    RandomListNode *copyRandomList(RandomListNode *head) {
	  if (!head) {
		  return head;
	  }
	  RandomListNode *head_tmp = head;
	  RandomListNode *new_head = new RandomListNode(head->label);
	  RandomListNode *new_head_tmp = new_head;
	  head_tmp = head_tmp->next;

	  map<RandomListNode *, RandomListNode *> mapper;
	  mapper[head] = new_head;
	  while (head_tmp) {
		  RandomListNode *new_node = new RandomListNode(head_tmp->label);
		  new_head_tmp->next = new_node;
		  new_head_tmp = new_head_tmp->next;
          mapper[head_tmp] = new_head_tmp;
		  head_tmp = head_tmp->next;
		  
	  }

	  head_tmp = head;
	  new_head_tmp = new_head;
	  while (head_tmp) {
		  if (head_tmp->random) {
			new_head_tmp->random = mapper[head_tmp->random];
		  }
		  head_tmp = head_tmp->next;
		  new_head_tmp = new_head_tmp->next;
	  }
	  return new_head;       
    }

算法2

我们把空间复杂度降为O(1),具体如下图所示:


第一次遍历原链表时把新节点加到原链表每个节点后面,

第二次遍历更新新节点的random指针,公式为:

new_head_tmp->random = old_head_tmp->random->next;

第三次遍历把原链表和新链表分开

代码如下:

    RandomListNode *copyRandomList(RandomListNode *head) {
	  if (!head) {
		  return head;
	  }
	  RandomListNode *old_head_tmp = head;
	  RandomListNode *new_head = new RandomListNode(head->label);
	  RandomListNode *new_head_tmp = new_head;
	  
	  new_head->next = head->next;
	  head->next = new_head;

	  old_head_tmp = old_head_tmp->next->next;
	  while (old_head_tmp) {
		  RandomListNode *new_node = new RandomListNode(old_head_tmp->label);
		  new_node->next = old_head_tmp->next;
		  old_head_tmp->next = new_node;
		  old_head_tmp = old_head_tmp->next->next;
	  }

	  old_head_tmp = head;
	  new_head_tmp = head->next;
	  while (old_head_tmp) {
		  if (old_head_tmp->random) {
			  new_head_tmp->random = old_head_tmp->random->next;
		  }
          old_head_tmp = old_head_tmp->next->next;
          
		  new_head_tmp = old_head_tmp!=nullptr?new_head_tmp->next->next:nullptr;
	  }

	  old_head_tmp = head;
	  new_head_tmp = head->next;
	  while (old_head_tmp) {
		  old_head_tmp->next = old_head_tmp->next->next;
		  new_head_tmp->next = old_head_tmp->next != nullptr ? new_head_tmp->next->next : nullptr;
		  old_head_tmp = old_head_tmp->next;
		  new_head_tmp = new_head_tmp->next;
	  }
	  return new_head;      
    }

猜你喜欢

转载自blog.csdn.net/qq_26410101/article/details/80428755
今日推荐