• 35 复杂链表的复制( 分解让复杂问题简单)


    题目描述:

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

    测试用例:

    功能测试(节点中的random指向自身;两个节点的random形成环状结构;链表中只有一个节点)

    特殊输入测试(空链表nullptr)

    解题思路:

    1)分成三步:

    一、根据原始链表创建每个节点N对应的N’。把每个N' 连接到N的后面。(插入到原结点后方)

    二、赋值节点的random指针

    三、拆分两个链表

    class Solution {
    public:
        RandomListNode* Clone(RandomListNode* pHead)
        {
            CloneNodes(pHead);
            ConnectRandomNodes(pHead);
            return ReConnectNodes(pHead);
        }
        
        //第一步 在原链表每个节点的后面复制链表
         void CloneNodes(RandomListNode* pHead){
             RandomListNode* pNode= pHead;
             while(pNode){
                 RandomListNode* pClone = new RandomListNode(pNode->label); //构造函数要传值
                 pClone->next = pNode->next;
                 pClone->random = nullptr;
                 
                 pNode->next = pClone;
                 pNode = pClone->next;
             }
         }
        
        //第二步 对random赋值
        void ConnectRandomNodes(RandomListNode* pHead){
            RandomListNode* pNode= pHead;
            while(pNode){
                RandomListNode* pClone = pNode->next;
                if(pNode->random)
                    pClone->random = pNode->random->next;
                
                pNode = pClone->next;
            }
        }
        
        //第三步 拆分链表
        RandomListNode* ReConnectNodes(RandomListNode* pHead){
            RandomListNode* pNode= pHead;
            RandomListNode* pCloneHead= nullptr;
            RandomListNode* pCloneNode= nullptr;
            
            if(pNode){//处理头节点
                pCloneHead=pCloneNode=pNode->next;
                pNode->next = pCloneNode->next;
                pNode = pNode->next;
            }
            
            while(pNode){
                pCloneNode->next = pNode->next; //连接复制的链表
                pCloneNode = pNode->next; 
                pNode->next = pCloneNode->next; //连接原来的链表
                pNode = pNode->next;
            }
            return pCloneHead;
        }
        
    };
    

    2)哈希表方法

    分为两步:

    一、复制原始列表的val与next,random置空,并使用哈希表存储<N,N'>的配对信息。

    二、设置复制链表上的每个random指针。

    class Solution {
    public:
        RandomListNode* Clone(RandomListNode* pHead)
        {
            if(pHead==NULL)
                return NULL;
             
            //定义一个哈希表
            unordered_multimap<RandomListNode*,RandomListNode*> table;
             
            // 开辟一个头结点
            RandomListNode* pClonedHead=new RandomListNode(pHead->label);
            pClonedHead->next=NULL;
            pClonedHead->random=NULL;
             
            // 将头结点放入map中
            table.insert(make_pair(pHead,pClonedHead));
             
            //设置操作指针
            RandomListNode* pNode=pHead->next;
            RandomListNode* pClonedNode=pClonedHead;
             
            // 第一遍先将简单链表复制一下
            while(pNode!=NULL)
            {
                // 不断开辟pNode的拷贝结点
                RandomListNode* pClonedTail=new RandomListNode(pNode->label);
                pClonedTail->next=NULL;
                pClonedTail->random=NULL;
                 
                //连接新节点,更新当前节点
                pClonedNode->next=pClonedTail;
                pClonedNode=pClonedTail;
                 
                //将对应关系  插入到哈希表中
                table.insert(make_pair(pNode,pClonedTail));
                 
                //向后移动操作节点
                pNode=pNode->next;
            }
             
            //需从头开始设置random节点,设置操作指针
            pNode=pHead;
            pClonedNode=pClonedHead;
             
            // 根据map中保存的数据,找到对应的节点
            while(pNode!=NULL)
            {
                 
                if(pNode->random!=NULL)
                {
                    //找到对应节点,更新复制链表
                    pClonedNode->random=table.find(pNode->random)->second;
                }
                 
                //向后移动操作节点
                pNode=pNode->next;
                pClonedNode=pClonedNode->next;
            }
             
            return pClonedHead;
             
        }
    };
    

    3)使用map存储<N,N'>的配对信息  

    class Solution {
    public:
        RandomListNode* Clone(RandomListNode* pHead)
        {
            if(pHead==NULL) return NULL;
     
            map<RandomListNode*,RandomListNode*> m;
            RandomListNode* pHead1 = pHead;
            RandomListNode* pHead2 = new RandomListNode(pHead1->label);
            RandomListNode* newHead = pHead2;
            m[pHead1] = pHead2;
            while(pHead1){
                if(pHead1->next) pHead2->next = new RandomListNode(pHead1->next->label);
                else pHead2->next = NULL;
                pHead1 = pHead1->next;
                pHead2 = pHead2->next;
                m[pHead1] = pHead2;
            }
     
            pHead1 = pHead;
            pHead2 = newHead;
            while(pHead1){
                pHead2->random = m[pHead1->random];
                pHead1 = pHead1->next;
                pHead2 = pHead2->next;
            }
            return newHead;
        }
    };
    

      

      

  • 相关阅读:
    2. Python语言基本语法
    wx.onMenuShareTimeline使用注意事项
    a different object with the same identifier value was already associated with the session:
    linux 下压缩大批量文件
    mysql sleep进程过多,应用级配置
    一次心惊肉跳的服务器误删文件的恢复过程
    分享一个css3写的气泡对话框,适合于即时通讯和留言本的动态内容
    一次Mysql 死锁事故
    adb server is out of date. killing...
    Redis 数据序列化方法 serialize, msgpack, json, hprose 比较
  • 原文地址:https://www.cnblogs.com/GuoXinxin/p/10480041.html
Copyright © 2020-2023  润新知