《从头再来》剑指offer.35 复杂链表的复制

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

本题主要的难点就是random指针不好理解。

 

第一种方法:采用哈希表来解决。首先定义一个指针和一个哈希表,指针指向链表头部,然后遍历链表构建原链表节点和新链表对应节点的键值对关系,即创建一个和原链表一模一样的键值(new Node),然后再次遍历构建新链表各节点的next和random引用指向。最后返回哈希表的头节点即可。

/*
// 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*> map;
        Node* cur = head;

        //建表
        while(cur != nullptr){
            map[cur] = new Node(cur->val);//因为是利用当前节点的值创建一个新的节点,所以一定要new Node(cur->val)
            cur = cur->next;
        }

        cur = head;
        while(cur != nullptr){
            map[cur]->next = map[cur->next];
            map[cur]->random = map[cur->random];
            cur = cur->next;
        }

        cur = head;
        return map[cur];
    }
};

第二种方法:采用复制、拼接,构建指向关系,最后拆分的方案。

需要注意的时,复制节点的时候,要先使构建节点的next指向cur的next,再使cur的next指向构建的节点,移动cur指针时,cur应该直接指向copy的next。

/*
// 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;

        //1、复制+拼接
        Node* cur = head;
        while(cur != nullptr){
            //新建一个和cur一模一样的节点,并拼接
            Node* copy = new Node(cur->val);
            copy->next = cur->next;
            cur->next = copy;
            //移动cur
            cur = copy->next;
        }

        //2、构建指向关系
        cur = head;//位置指针回到开头
        while(cur != nullptr){
            if(cur->random != nullptr){
                cur->next->random = cur->random->next;
            }
            //移动位置指针
            cur = cur->next->next;
        }

        //3、拆分
        //定义两个新节点,一个指向原链表的头节点,一个指向拆分后新链表的头节点
        Node* old = head;
        Node* newList = head->next;
        cur = head->next;
        while(cur->next != nullptr){
            old->next = old->next->next;
            cur->next = cur->next->next;

            //移动指针
            old = old->next;
            cur = cur->next;
        }
        old->next = nullptr;
        return newList;
        
    }
};

《从头再来》

posted @ 2021-06-03 22:03  丶原来是枝知啊i  阅读(65)  评论(0)    收藏  举报