面试题35:复杂链表的复制(C++)

题目地址:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/

题目描述

请实现copyRandomList函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个next指针指向下一个节点,还有一个random指针指向链表中的任意节点或者null。

题目示例

示例 1:

 

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:

 

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例 3:

 

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例 4:

输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。

解题思路

分析题目可知,这里要求的复制链表并不是我们常常所说的链表元素复制,因为它不仅涉及了next指针还涉及到了另一个指针random,所以它是一种深拷贝。

这里要区别一下深拷贝和浅拷贝区别:浅拷贝只复制指向某个对象的指针,而不复制对象本身,复制前后的对象依旧是共享同一内存块,但深拷贝会类似于我们所说的复制粘贴操作,它额外创造一个新对象并将旧对象复制给新对象,新对象跟原对象不共用同一内存块,修改新对象并不会改到原对象。

思路1:复制链表并拆分。直接在原链表基础上复制新链表,即让原节点next指向自己的拷贝节点,然后拆分random, 拷贝节点的random指向其指向的原节点的next,最后,再拆next,让其每一个节点next都指向其原来指向的下一节点,文字描述有点晦涩,直接上图(图中合并部分,即拷贝过程中,由于空间有限,没有画出原有链表的random指向,其实原有链表的指向和拷贝之前的一样)

  • Step1:复制原链表中每一个节点,使得拷贝后的新节点在原节点的下一个节点;
  • Step2:拷贝后的新节点的random指向节点与原链表节点的random指向节点一致;
  • Step3:拆分链表,原节点依次连接,拷贝后的新节点依次连接。

思路2:使用哈希表map表示映射关系,其中哈希表的键值key是原节点,value值是复制的新节点。具体流程可以分为二步,第一步是遍历原链表,利用哈希表映射新节点和旧节点关系,即每遍历一个节点,则复制一个val值相同的新节点,mp[p]= new Node(p->val)。第二步是遍历map,复制next和random指针的对应关系,并更新新节点的next和random所指的值,最后返回新链表的头节点即可,即即mp[p]->next=mp[p->next]和mp[p]->random=mp[p->random]。

思路3:在使用哈希表的基础上,用DFS优化程序

程序源码

合并+拆分

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr) return nullptr;
        Node* newHead = head;
        while(newHead)
        {
            Node* p = new Node(newHead->val);
            Node* q = newHead->next;
            newHead->next = p;
            p->next = q;
            newHead = p->next;
        }
        newHead=head//头节点
        while(newHead)
        {
            if(newHead->random)
                newHead->next->random=newHead->random->next;
            newHead=newHead->next->next;
        }
        newHead = head;
        Node* t = head->next;
        Node* pHead = head->next;
        while(newHead)
        {
            newHead->next = newHead->next->next;
            newHead = newHead->next;
            if(t->next)
            {
                t->next = t->next->next;
                t = t->next;
            }
        }
        return pHead;
    }
};

哈希表

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
       if(head == nullptr) return nullptr;
       unordered_map<Node*, Node*> mp;
       Node* p = head;
       while(p)
       {
           mp[p] = new Node(p->val);
           p = p->next;
       }
       p = head;
       while(p)
       {
           if(p->next != nullptr)
           {
               mp[p]->next = mp[p->next];
           }
           if(p->random != nullptr)
           {
               mp[p]->random = mp[p->random];
           }
           p = p->next;
       }
       return mp[head];
};

哈希+DFS

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        unordered_map<Node*, Node*> mp;
        dfs(head, mp);
        return mp[head];
    }
    Node* dfs(Node* head, unordered_map<Node*, Node*> &mp)
    {
        if(head == nullptr) return nullptr;
        if(mp.count(head)) return mp[head];
        mp[head] = new Node(head->val);
        mp[head]->next = dfs(head->next, mp);
        mp[head]->random = dfs(head->random, mp);
        return mp[head];
    }
};
----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
原文地址:https://www.cnblogs.com/wzw0625/p/12682294.html