LeetCode: 138. 复制带随机指针的链表 - Python

15 篇文章 0 订阅

问题描述:

138. 复制带随机指针的链表

请实现函数ComplexListNode* Clone(ComplexListNode*pHead),复制一个复杂链表。在复杂链表中,每个节点除了有一个m_pNext指针指向下一个节点,还有一个m_pSibling指针指向链表中的任意节点或者nullptr

节点的C++定义如下(后面代码均为C++代码段):

struct ComplexListNode
{
int                m_nValue;
ComplexListNode*   m_pNext;
ComplexListNode*   m_pSibling;
};

例如(一个包含5个节点的复杂链表):
在这里插入图片描述

问题分析:

总结一下昨天小米算法校招现场面试,首先是,面试官很 nice,就是你不会,人家也会引导你,很有耐心。一面的时候比较基础,各种算法推导等,出了一个二叉树的遍历(S 型遍历,层次遍历的一种,广度优先队列实现即可)。二面的时候,先做两道算法题目,第一个就是本次要总结的题目《复杂链表的复制》,比较遗憾,当时没能给出时间复杂度为O(n) 解决方法,这也是要总结的原因,第二个题目是《二叉树的最近公共祖先》,这个倒是给出了解决方法。后来看了一下,发现那个题目是《剑指offer》上的,看来还是自己没准备好呀。现在参考这本学习一下,书中提供了三种方法,前两中,面试的时想到了,现在就学习一下最后一种方法(时间复杂度O(n),空间复杂度为O(1) ),具体思路分三步:

(1) 对应着原始链表中的每一个节点,复制,并插入当前节点的后面(这一过程只操作m_pNext指针,看下图,新复制的节点表示为: N ′ N^{'} N
在这里插入图片描述

节点复制代码如下:

void CloneNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode = pHead;
    while(pNode != nullptr)
    {
        ComplexListNode* pCloned = new ComplexListNode();
        pCloned->m_nValue = pNode->m_nValue;
        pCloned->m_pNext = pNode->m_pNext;
        pCloned->m_pSibling = nullptr;
 
        pNode->m_pNext = pCloned;
 
        pNode = pCloned->m_pNext;
    }
}

(2)(1) 的基础上,把每个新复制的节点m_pSibling指针信息补上,怎么补?看一个例子,假设原始链表上的节点 Nm_pSibling指针指向节点 S,很显然此时,Nm_pNext 指向 N ′ N^{'} NSm_pNext 指向 S ′ S^{'} S ,利用这些信息,就可以完成m_pSibling信息补全。补全后如下图:
在这里插入图片描述

节点 m_pSibling 补全代码如下:

void ConnectSiblingNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode = pHead;
    while(pNode != nullptr)
    {
        ComplexListNode* pCloned = pNode->m_pNext;
        if(pNode->m_pSibling != nullptr)
        {
            pCloned->m_pSibling = pNode->m_pSibling->m_pNext;
        }
 
        pNode = pCloned->m_pNext;
    }
}

(3)(2) 得到链表拆分成两链表,奇数位节点重新恢复为原始链表,偶数位节点重新连接,就得到了,新复制的链表。
在这里插入图片描述

重组代码如下:

ComplexListNode* ReconnectNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode = pHead;
    ComplexListNode* pClonedHead = nullptr;
    ComplexListNode* pClonedNode = nullptr;
 
    if(pNode != nullptr)
    {
        pClonedHead = pClonedNode = pNode->m_pNext;
        pNode->m_pNext = pClonedNode->m_pNext;
        pNode = pNode->m_pNext;
    }
 
    while(pNode != nullptr)
    {
        pClonedNode->m_pNext = pNode->m_pNext;
        pClonedNode = pClonedNode->m_pNext;
 
        pNode->m_pNext = pClonedNode->m_pNext;
        pNode = pNode->m_pNext;
    }
 
    return pClonedHead;
}

递归方式实现:

# LeetCode: 138. 复制带随机指针的链表


class Solution:
    def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':

        my_dict = {}

        def copynode(node):

            if node is None: return None
            
            if my_dict.get(node): 
                return my_dict.get(node)

            root = Node(node.val)  # 存入字典
            my_dict[node] = root
            
            root.next = copynode(node.next)  # 继续获取下一个节点
            root.random = copynode(node.random)  # 继续获取下一个随机节点

            return root

        return copynode(head)

声明: 总结学习,有问题或不妥之处,可以批评指正哦。

参考说明:

题目、图片来源:《剑指offer》第二版,现场面试题
书中、代码参考:github.com/zhedahht/CodingInterviewChinese2/blob/master/35_CopyComplexList/CopyComplexList.cpp

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值