当前位置:   article > 正文

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

复制带随机指针的链表 python

问题描述:

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

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

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

struct ComplexListNode
{
int                m_nValue;
ComplexListNode*   m_pNext;
ComplexListNode*   m_pSibling;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

例如(一个包含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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

(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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

(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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

递归方式实现:

# 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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

参考说明:

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/546258
推荐阅读
相关标签
  

闽ICP备14008679号