剑指Offer 系列 剑指 Offer 35:复杂链表的复制:很巧妙的一道题,强烈推荐

题目描述:

请实现 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。

解题思路:

这道题的思路很巧妙,我的感觉是,他给的数据中每个都有两个数据,而第二个数就是迷惑人的,这个数据没有任何作用,也无法用代码求出这个数据

因此解题的时候需要用其他的方法替代出这个数据:

  1. 先将每一个节点复制一遍,放在本节点的后面
  2. 此时根据原链表中每个节点的random,求出复制的节点的random。(这一步是关键)
  3. 将复制的节点分离出来返回

第一步和第三步就不用说了,这里解释一下第二步怎样求得,因为几乎是完全复制出来的新节点,所以新复制节点y的random就是原节点x的random的next;

如上图所示,如果B的random指向A,那么B1的random肯定是指向A1;

A1的求法就是B->random->next也就是B1->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) return NULL;
        Node *headx = head;
        //将每个节点复制到他后面
        while(headx)
        {
            auto x = new Node(headx->val);
            x->next = headx->next;
            headx->next = x;
            headx = x->next;
        }

        //将另一个指针也复制一次
        Node *heady = head;
        while(heady && heady->next)
        {
            if(heady->random)
                heady->next->random = heady->random->next;
            heady = heady->next->next;
        }

        //将两个分离
        Node *newhead = head->next;
        Node *headz = head;
        while(headz && headz->next)
        {
            Node *z = headz->next;
            headz->next = z->next;
            headz = z;
        }
        return newhead;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_46423166/article/details/110823410