【剑指offer】面试题35 复杂链表的复制

面试题–【剑指Offer】 题目解答

题目要求

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

解题分析

本题是一个十分复杂的过程,意在考察我们将大问题划分成那个若干个小问题的能力。最容易想到的方法是,先复制一遍链表,然后根据原链表中的节点random指针,再去对复制好的链表的random进行赋值,这里要定位random的指向,每次都要在链表中进行遍历和记录,平均时间复杂度O(n2)。显然不是我们需要的办法。

这里,我们把复制链表的过程分成以下三个子步骤:
1、就地复制每个节点,如:复制节点A得到A1,将A1插入节点A后面
2、遍历链表设置random,A1->random = A->random->next;
3、将链表拆分成原链表和复制后的链表

主要代码c++

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead == nullptr)
            return nullptr;
        // step1 复制链表,实际就是插入节点
        RandomListNode* pCurrent = pHead;
        while(pCurrent)
        {
            RandomListNode* pClone = new RandomListNode(pCurrent->label);
            pClone->next = pCurrent->next;
            pCurrent->next = pClone;
            pCurrent = pClone->next;
        }
        
        // step2 设置random指针,实际就是遍历链表
        pCurrent = pHead;
        while(pCurrent)
        {
            RandomListNode* pClone = pCurrent->next;
            if(pCurrent->random)
            {
                pClone->random = pCurrent->random->next;
            }
            pCurrent = pClone->next;
        }
        //step3 拆分链表,实际就是删除节点
        pCurrent = pHead;
        RandomListNode* pClone = pHead->next;
        while(pCurrent->next)// 原链表最后一个元素为复制后的倒数第二个元素
        {
          RandomListNode* pTmp = pCurrent->next;
          pCurrent->next = pTmp->next;
          pCurrent = pTmp;
        }
        return pClone;
    }
};

总结

把题目进行拆分的话,每一步的代码都很好写考察的知识点也比较明确,难点就是拆分链表的时候,有多种写法,这里边给出一种较为简单的基于删除节点思想的方法,不理解的话通过例子可以更加直观的去感受,实际上就是节点1和3,5,7等奇数点链接,节点2,4,6,8等偶数点链接。

你可能感兴趣的:(剑指offer)