### 这道题目来自《剑指 offer 》第二版面试题35。复杂链表中,每个节点除了有 next 指针外,还有一个指向兄弟的指针 sibling。以下是书中链表的声明:
```
struct ComplexListNode {
int m_nValue;
ComplexListNode *m_pNext;
ComplexListNode *m_pSibling;
};
```
思路:要做到O(n)的时间并不使用额外的辅助空间实现,书中分为三步实现:
1. 复制原始链表的每个节点 N 并创建新节点 N<sup>'</sup>,再把N<sup>'</sup>链接到 N 的后面。
2. 设置复制出来的节点的 m_pSibling。
3. 拆分链表。
以下是代码实现:
```
// 第一步
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;
}
}
// 第二步
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;
}
}
// 第三步
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;
}
// 综合
ComplexListNode* Clone(ComplexListNode *pHead)
{
CloneNodes(pHead);
ConnectSiblingNodes(pHead);
return ReconnectNodes(pHead);
}
```