138 Copy List with Random Pointer

17 篇文章 0 订阅
17 篇文章 0 订阅

1 题目

A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.

Return a deep copy of the list.

 

Example 1:

Input:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}

Explanation:
Node 1's value is 1, both of its next and random pointer points to Node 2.
Node 2's value is 2, its next pointer points to null and its random pointer points to itself.

2 尝试解

2.1 分析

给定一种特殊的链表,每个节点除了有指向后续节点的指针外,还有一个指针可以指向任意节点。要求复制此链表。简单的方法是,先按照顺序将每个节点及其后续指针复制一遍,同时用一个map保存原节点A到新节点A'的映射关系,即map[A]=A'。如果原节点A的任意指针指向了节点X,即A→random = X,则A'->random = X' = map[X] = map[A→random]。

这种方法需要遍历两遍原链表,时间复杂度为O(n)。同时需要额外的O(n)空间保存映射关系。

2.2 代码

class Solution {
public:
    Node* copyRandomList(Node* head) {
        Node* dummy = new Node(0,NULL,NULL);
        Node* p = head;
        Node* newp = dummy;
        map<Node*,Node*> dict;
        while(p != NULL){
            Node* temp = new Node(p->val,NULL,NULL);//initial:1(p)->2 copy:0(newp) 1
            newp->next = temp;   //initial:1->2 copy:0->1
            dict[p] = temp;  //map the old node to the new node
            p = p->next; //1->2(p), 0->1(newp)
            newp = newp->next;
        }
        p = head;
        newp = dummy->next;
        while(p != NULL){  //old1->old2, dict = {old1:new1,old2:new2} new1->random = dict[old1->random] 
            newp->random = p->random!=NULL?dict[p->random]:NULL;
            p = p->next;
            newp = newp->next;
        }
        return dummy->next;        
    }
};

3 标准解

3.1 分析

进阶要求为不适用额外的空间。上述做法中额外空间用来存储原节点与新节点之间的关联,如果不使用额外空间,可以在创建新节点后,将新节点直接放在原节点之后,即A→A'→B→B'→C→C'。

在第二次遍历链表时,复制random指向关系。如果A→random = X,则A'→random = X' = X→next = A→random→next。

在第三遍遍历链表时,将原链表与新链表再拆开。

3.2 代码

public RandomListNode copyRandomList(RandomListNode head) {
  RandomListNode iter = head, next;

  // First round: make copy of each node,
  // and link them together side-by-side in a single list.
  while (iter != null) {
    next = iter.next;

    RandomListNode copy = new RandomListNode(iter.label);
    iter.next = copy;
    copy.next = next;

    iter = next;
  }

  // Second round: assign random pointers for the copy nodes.
  iter = head;
  while (iter != null) {
    if (iter.random != null) {
      iter.next.random = iter.random.next;
    }
    iter = iter.next.next;
  }

  // Third round: restore the original list, and extract the copy list.
  iter = head;
  RandomListNode pseudoHead = new RandomListNode(0);
  RandomListNode copy, copyIter = pseudoHead;

  while (iter != null) {
    next = iter.next.next;

    // extract the copy
    copy = iter.next;
    copyIter.next = copy;
    copyIter = copy;

    // restore the original list
    iter.next = next;

    iter = next;
  }

  return pseudoHead.next;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值