链表面试题-复杂链表的复制

题目描述:
请实现函数ComplexListNode* Clone(ComplexListNode* Head),复制一个复杂链表,在复杂链表中,每个节点除了有一个_next指针指向下一个外,还有一个Sibling指针指向链表中的任意节点或者nullptr。


节点类型

struct ComplexListNode
{
    int _data;
    ComplexListNode* _next;
    ComplexListNode* _Sibling
}

这里写图片描述

第一直觉的思路是:

  1. 复制原链表的节点,用_next连接
  2. 设置每个节点的Sibling指针

由于找每个节点的Sibling指针都要遍历一次原链表,故这种思路的时间复杂度为O(N2)。

思考一下,上面这种思路的时间复杂度之所以高,是因为每次找Sibling指针都要遍历链表,所以很耗时,稍加思索就可以想到如何在查找上优化,没错,就是哈希表。

可以将原链表的Sibling指针存入一个哈希表中,这样每次查找就是O(1)的复杂度,这样,整个过程的时间复杂度就是O(N),不过哈希表需要额外的空间复杂度开销。

这里介绍剑指offer上的思路,在不需要额外空间复杂度的情况下,依然是O(N)的时间复杂度。

算法的思路:

第一步: 根据原链表中的每个节点N创建对应的复制节点N’,然后将N‘连接在N后面
这里写图片描述

此步骤代码:

void CloneNode(ComplexListNode* Head)
{
    ComplexListNode* node = Head;
    while(node){
        ComplexListNode* Cloned = new ComplexListNode();
        Cloned->_data = node->_data;
        Cloned->_next = node->_next;
        Cloned->_Sibling = nullptr;

        //克隆出的节点连在原节点后面
        node->_next = Cloned;
        node = Clone->_next;
    }
}

第二步:设置复制出来的节点的Sibling。假定原链表中N的Sibling指向S,那么其对应复制出来的N’是N的_next指向的节点同理,S’也是S的_next指向的节点。故如下:
这里写图片描述

完成第二步的代码

void ConnectSiblingNodes(ComplexListNode* Head)
{
    ComplexListNode* node = Head;
    while(node){
        ComplexListNode* Cloned = node->_next;
        if(node->_Sibling){
            Cloned->_Sibling = node->_Sibling->_next;
        }
        node = Cloned->_next;
    }
}

第三步:整个链表现在奇数位为原始链表的节点,偶数位是复制出来的节点,拆分成两个链表即可。
这里写图片描述

完成此步骤的代码:

ComplexListNode* ReConnectNodes(ComplexListNode* Head)
{
    ComplexListNode* node = Head;
    ComplexListNode* ClonedHead = nullptr;
    ComplexListNode* Clonednode = nullptr;

    if(node){
        ClonedHead = Clonednode = node->_next;
        node = Clonenode->_next;
        node = node->_next;
    }

    while(node){
        Clonednode->_next = node->_next;
        Clonednode = Clonednode->_next;
        node->_next = Clonednode->_next;
        node = node->_next;
    }
    return ClonedHead;
}

然后这三步合起来即可:

ComplexListNode* Clone(ComplexListNode *Head)
{
    CloneNodes(Head);
    ConnectSibling(Head);
    return ReConnectNodes(Head);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值