zoukankan      html  css  js  c++  java
  • 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;
        }
    };
    

      

      

  • 相关阅读:
    Java Web 网络留言板2 JDBC数据源 (连接池技术)
    Java Web 网络留言板3 CommonsDbUtils
    Java Web ConnectionPool (连接池技术)
    Java Web 网络留言板
    Java Web JDBC数据源
    Java Web CommonsUtils (数据库连接方法)
    Servlet 起源
    Hibernate EntityManager
    Hibernate Annotation (Hibernate 注解)
    wpf控件设计时支持(1)
  • 原文地址:https://www.cnblogs.com/GuoXinxin/p/10480041.html
Copyright © 2011-2022 走看看