题目描述:http://ac.jobdu.com/problem.php?pid=1524
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点)。
注:以下解析来自程序员面试题精选100题(49)-复杂链表的复制[算法]精简。
第一步,为原始链表的每个节点N创建对应的节点N’,并把N’插入到N的后面
第二步,设置复制出来的节点的sibling, N’的sibling指向N的sibling的next
第三步,拆分链表,奇数个节点组成原始链表,偶数个节点组成复制出的链表
// 复制节点
void CloneNodes(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
while (pNode != NULL) {
ComplexListNode* pCloneNode = new ComplexListNode(pNode->m_nValue);
pCloneNode->m_pNext = pNode->m_pNext;
pCloneNode->m_pSibling = NULL;
pNode->m_pNext = pCloneNode;
pNode = pCloneNode->m_pNext; //指向下一个节点
}
}
// 设置sibling
void ConnectSibling(ComplexListNode* pHead)
{
ComplexListNode* pNode = pHead;
while (pNode != NULL) {
if (pNode->m_pSibling)
pNode->m_pNext->m_pSibling = pNode->m_pSibling->m_pNext;
pNode = pNode->m_pNext->m_pNext;
}
}
// 拆分
ComplexListNode* DetachList(ComplexListNode* pHead)
{
if (pHead == NULL) {
return NULL;
}
ComplexListNode* pCloneHead = pHead->m_pNext;
ComplexListNode* pCloneNode = pCloneHead;
ComplexListNode* pNode = pHead;
pNode->m_pNext = pCloneNode->m_pNext;
pNode = pNode->m_pNext; // pNode先走一步,容易判断是否到链表尾
while (pNode) {
pCloneNode->m_pNext = pNode->m_pNext;
pCloneNode = pCloneNode->m_pNext;
pNode->m_pNext = pCloneNode->m_pNext;
pNode = pNode->m_pNext;
}
return pCloneHead;
}
// 三步组合,时间复杂度O(n),空间复杂度O(n)但没有使用额外的空间
ComplexListNode* Clone(ComplexListNode* pHead) {
CloneNodes(pHead);
ConnectSibling(pHead);
return DetachList(pHead);
}