• 【剑指offer】复杂链表的复制


    原创文章,转载请注明出处!

    本题牛客网地址

    博客文章索引地址

    博客文章中代码的github地址

    1.题目

          输入一个复杂链表,返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)。

    • 复杂链表的数据结构

          每个节点包含以下三个部分:节点值label,一个指向下一个节点next的指针,一个指向任意一个节点random的特殊指针。 

    struct RandomListNode 
    {
        int label;
        struct RandomListNode *next;
        struct RandomListNode *random;    
    }
    • 复杂链表实例(含有5个节点的复杂链表)

    image

    2.思路

      复杂链表的复制过程分成3个步骤,每个步骤的图形化方式如下:

    • 新建复制节点的label和next、random

              根据原链表上的每个节点N创建节点N’,然后把创建出来的节点用next连接起来

    剑指Offer(二十五):复杂链表的复制

    • 调整复制节点的random

    剑指Offer(二十五):复杂链表的复制

    • 拆分链表,其中奇数是原链表,偶数是复制的链表。

    剑指Offer(二十五):复杂链表的复制

    3.代码

          复杂链表的复制分成三个步骤,每个步骤定义一个子函数。

    class Solution {
    public:
        RandomListNode* Clone(RandomListNode* pHead)
        {
            // 第一步:复制原链表的节点,label和next
            CloneNodes(pHead);
            // 第二步:复制原链表的节点,random
            ConnectRandom(pHead);
            // 第三步:链表拆分,奇数是原链表,偶数是新链表
            return ReconnectNodes(pHead);
        }
        
        // 第一步
        void CloneNodes(RandomListNode* pHead)
        {
            // 遍历指针
            RandomListNode* pNode = pHead;
    
            while(pNode!=nullptr)
            {
                // 创建节点(节点值)
                RandomListNode * pCloned = new RandomListNode(pNode->label);
    
                // 节点指针
                pCloned->next = pNode->next;
                pCloned->random = pNode->random;
    
                // 节点连接
                pNode->next = pCloned;
    
                // 节点移动
                pNode = pCloned->next;
            }
        }
        
        // 第二步
        void ConnectRandom(RandomListNode* pHead)
        {
            // 遍历节点
            RandomListNode* pNode=pHead;
            RandomListNode* pCloned=nullptr;
            while(pNode!=nullptr)
            {
                // 建立连接
                pCloned = pNode->next;
                
                if(pNode->random!=nullptr)
                {
                    pCloned->random = pNode->random->next;
                }
                
                pNode = pCloned->next;
            }
        }
        
        // 第三步
        RandomListNode* ReconnectNodes(RandomListNode* pHead)
        {
            // 遍历指针
            RandomListNode* pNode = pHead;
            RandomListNode* pClonedHead = nullptr;
            RandomListNode* pClonedNode = nullptr;
    
            // 头结点
            if(pNode!=nullptr)
            {
                pClonedHead = pClonedNode = pNode->next;// clone赋值
                pNode->next = pClonedNode->next;        // node断链
                pNode = pNode->next;                    // node移位
            }
         // 循环移位  while(pNode!=nullptr) { pClonedNode->next = pNode->next; // clone断链 pClonedNode = pClonedNode->next; // clone移位 pNode->next = pClonedNode->next; // node断链 pNode = pNode->next; // node移位 } return pClonedHead; } };

      

  • 相关阅读:
    Ubuntu 侧边栏和顶栏设置
    ubuntu 下安装微软字体和 console
    vim 的 auto-pairs 设置
    linux上的常用的一些操作
    断点模式
    GIT(git)简单操作
    制表符 的用法
    如何解决ASCII 字符显示不出来的情况
    01_js 快速入门
    神代码,结束进程神方法
  • 原文地址:https://www.cnblogs.com/wanglei5205/p/8696393.html
Copyright © 2020-2023  润新知