最近看到一道有关链表复制的算法题,解法很是奇妙。
题目:已知一链表,每个节点除了有一个指向下一节点的指针外,还有一随机指针指向链表中的任意节点(可能为空,也有可能为自身),请复制一个链表,要求节点的顺序以及节点上的随机指针指向的节点位置和原链表一致。
这个题目有个很巧妙的解法,可以达到O(n)的效率,其中心思想是把原始链表和复制链表先合并为一个有固定顺序的链表然后给复制链表中每个节点的随机指针复制,最后再打断链表恢复原样。
/**********节点信息*********/
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;
}