题目:已知一链表,每个节点除了有一个指向下一节点的指针外,还有一随机指针指向链表中的任意节点(可能为空,也有可能为自身),请复制一个链表,要求节点的顺序以及节点上的随机指针指向的节点位置和原链表一致。
![一道奇妙的链表复制问题 一道奇妙的链表复制问题](http://hiphotos.baidu.com/%B3%A3%D1%C5%C3%F4/pic/item/fbe4321ae53635b5af513319.jpg)
这个题目有个很巧妙的解法,可以达到O(n)的效率,其中心思想是把原始链表和复制链表先合并为一个有固定顺序的链表,然后给复制链表中每个节点的随机指针复制,最后再打断链表恢复原样。
![一道奇妙的链表复制问题 一道奇妙的链表复制问题](http://hiphotos.baidu.com/%B3%A3%D1%C5%C3%F4/pic/item/f35a0fdfc8af441b94ee3719.jpg)
代码如下:
typedef struct __Node {
int nData;
__Node* pNext;
__Node* pRandom;
} Node;
Node* DuplicateList(Node* pSrcListHead)
{
if (pSrcListHead == NULL)
return NULL;
Node* pNode = pSrcListHead;
while (pNode != NULL)
{
Node* pNewNode = new Node;
pNewNode->nData = pNode->nData;
pNewNode->pNext = pNode->pNext;
pNewNode->pRandom = pNode->pRandom;
pNode->pNext = pNewNode;
pNode = pNewNode->pNext;
}
Node* pDestListHead = pSrcListHead->pNext;
pNode = pSrcListHead;
while (pNode != NULL)
{
pNode->pNext->pRandom = pNode->pRandom->pNext;
pNode = pNode->pNext->pNext;
}
pNode = pSrcListHead;
Node* pNode2 = pNode->pNext;
while (pNode != NULL)
{
pNode->pNext = pNode2->pNext;
pNode = pNode->pNext;
if (pNode)
pNode2->pNext = pNode->pNext;
else
pNode2->pNext = NULL;
pNode2 = pNode2->pNext;
}
return pDestListHead;
}
不过目前还未考虑到原始链表有环的情况,如果原始链表有环,则应该先求出环的入口点,然后利用上面的方法进行链表复制。