赞
踩
请实现函数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
指针信息补上,怎么补?看一个例子,假设原始链表上的节点 N 的m_pSibling
指针指向节点 S,很显然此时,N 的m_pNext
指向
N
′
N^{'}
N′ ,S 的m_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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。