zoukankan      html  css  js  c++  java
  • 面试题35:复杂链表的复制

    请实现函数RandomList* Clone(RandomList* pHead),复制一个复杂链表。在复杂链表中,每个节点除了有一个next指针,还有一个指向任意一个节点的random指针。

    解题思路

      这个题目可以分两步来完成:

    • 遍历节点的next指针,先复制出所有的节点
    • 遍历所有节点的random指针,并修改复制链表的random指针

      通常第一步很简单,可以当做简单链表的复制来解决,但主要是第二步,有几种方案,但是需要一个最优的(复杂度最低的)方案。

    • 遍历所有原链表节点,如果某节点存在random节点,那需要从头再遍历一次找到这个节点,时间复杂度O(n^2)
    • 第一步遍历所有节点,如果某节点存在random节点,则用HashMap保存这个关系,找到random节点的复杂度可为O(1)
    • 在第一步复制链表的过程中,将复制链表放在原链表的后面

      第三种方案是最妙的方案,但是需要将所有复制过程分为3步。分别是复制链表、复制随机指针、分割链表

    // 定义复杂链表
    struct RandomListNode{
        int label;
        RandomListNode* next;
        RandomListNode* random;
        RandomListNode(int label):label(label), next(nullptr), random(nullptr){}
    };
    
    // 普通链表的复制(复制后的链表与原链表无任何关系)
    ListNode* cloneBase(ListNode* pHead){
        ListNode* pNode = pHead;
        ListNode* pAns = nullptr;
        ListNode* pAsses = nullptr;
    
        while(pNode != nullptr){
            // 处理头结点
            if(pAns == nullptr){
                pAns = new ListNode(pNode->val);
                pAsses = pAns;
            }
            pNode = pNode->next;
            if(pNode != nullptr){
                ListNode* pClone = new ListNode(pNode->val);
                pAsses->next = pClone;
                pAsses = pAsses->next;
            }
            else
                pAsses->next = nullptr;
        }
        return pAns;
    }
    
    // 复杂链表的复制
    void CloneNodes(RandomListNode* pHead){
        if(pHead == nullptr)
            return ;
    
        RandomListNode* pNode = pHead;
        while(pNode != nullptr){
            RandomListNode* pCloned = new RandomListNode(pNode->label);
            pCloned->next = pNode->next;
            pCloned->random = nullptr;
    
            pNode->next = pCloned;
            pNode = pCloned->next;
        }
    }
    
    // 复制链表的第二部分
    void ConnectRandomNodes(RandomListNode* pHead){
        RandomListNode* pNode = pHead;
        while(pNode != nullptr){
            RandomListNode* pCloned = pNode->next;
            if(pNode->random != nullptr){
                pCloned->random = pNode->random->next;
            }
            pNode = pCloned->next;
        }
    }
    
    RandomListNode* Clone(RandomListNode* pHead){
        CloneNodes(pHead);
        ConnectRandomNodes(pHead);
    
        RandomListNode* pNode = pHead;
        RandomListNode* pCloneHead = nullptr;
        RandomListNode* pCloneNode = nullptr;
    
        // 先复制头指针
        if(pNode != nullptr){
            pCloneHead = pNode->next;
            pCloneNode = pCloneHead;
            // 修改pNode的下一个
            pNode->next = pCloneNode->next;
            pNode = pNode->next;
        }
        while(pNode != nullptr){
            pCloneNode->next = pNode->next;
            pCloneNode = pCloneNode->next;
            pNode->next = pCloneNode->next;
            pNode = pNode->next;
        }
        return pCloneHead;
    }
    
    文末附上普通链表的复制
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <cstring>
    #include "ListNode.h"
    #include "TreeNode.h"
    #include "Graph.h"
    using namespace std;
    
    #define MAXNUM 100010
    #define DRIFT 1001
    
    // 普通链表的复制(复制后的链表与原链表无任何关系)
    ListNode* cloneBase(ListNode* pHead){
    
        ListNode* pNode = pHead;
        ListNode* pAns = nullptr;
        ListNode* pAsses = nullptr;
    
        while(pNode != nullptr){
            // 处理头结点
            if(pAns == nullptr){
                pAns = new ListNode(pNode->val);
                pAsses = pAns;
            }
    
            pNode = pNode->next;
            if(pNode != nullptr){
                ListNode* pClone = new ListNode(pNode->val);
                pAsses->next = pClone;
                pAsses = pAsses->next;
            }
            else
                pAsses->next = nullptr;
        }
        return pAns;
    }
    
    int main()
    {
        ListNode* pNode1 = createListNode(1);
        ListNode* pNode2 = createListNode(2);
        ListNode* pNode3 = createListNode(3);
        ListNode* pNode4 = createListNode(4);
        ListNode* pNode5 = createListNode(5);
    
        connectListNodes(pNode1, pNode2);
        connectListNodes(pNode2, pNode3);
        connectListNodes(pNode3, pNode4);
        connectListNodes(pNode4, pNode5);
        ListNode* pClone = cloneBase(pNode1);
    
    
        removeNode(&pClone, 4);
        PrintListNodes(pClone);
        PrintListNodes(pNode1);
        return 0;
    }
    
  • 相关阅读:
    二分图 洛谷P2055 [ZJOI2009]假期的宿舍
    并查集 洛谷P1640 [SCOI2010]连续攻击游戏
    贪心 洛谷P2870 Best Cow Line, Gold
    贪心 NOIP2013 积木大赛
    快速幂 NOIP2013 转圈游戏
    倍增LCA NOIP2013 货车运输
    树形DP 洛谷P2014 选课
    KMP UVA1328 Period
    动态规划入门 BZOJ 1270 雷涛的小猫
    KMP POJ 2752Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/flyingrun/p/13518845.html
Copyright © 2011-2022 走看看