您的位置:首页 > Web前端

剑指offer - 复杂链表的复制

2015-10-02 18:07 531 查看
题目:实现函数 ComplexListNode* Clone( ComplexListNode* pHead ), 复制一个复杂链表,在复杂链表中除了有一个 pNext 指针指向下一个结点外,还有一个 pSibling 指向链表中的任意结点或者NULL, 结点定义如下:

struct  ComplexListNode{
	int   value;
	ComplexListNode*  pNext;
	ComplexListNode*  pSibling;
};


对于这个问题,有三种思路:

思路1:第一步先复制原始链表的每一个结点,并用 pNext 链接起来。第二步设置每个结点的 pSibling 指针。假设原始链表中某个结点N的pSibling指向结点S,由于S的位置在链表中的遍历时间复杂度为 O(n),这个对于一个含有n个结点的链表,该方法总的时间复杂度为 O(n^2);

思路2:在上面的算法中,由于时间复杂度主要花费在定位结点 pSibling 上,因此可以试着在这方面去做优化。我们还是分为两步,第一步复制原始链表上的每个结点N创建N‘, 然后把这些创建出来的结点用 pNext 连接起来,同时把 <N, N'> 的配对信息存在一个哈希表中。 第二步还是设置复制链表上每个结点的 pSibling。如果在原始链表中结点N的pSibling指向某个结点S, 那么在复制链表中对应的N’应该指向S。而有了哈希表,我们就可以在O(1)时间根据S找到S’了。此方法是利用了空间换取时间。通过一个大小为O(n)的哈希表,使得该算法的时间复杂度从O(n^2)变到
O(n);

★思路3:在不利用辅助空间的情况下,我们依旧复制原始链表的每个结点N来创建对应的N‘, 只是这次把N’ 链接在结点N的后面。完成这步的代码如下:

void  CloneNodes( ComplexListNode * pHead ){
	ComplexListNode *pNode = pHead;
	while( pNode != NULL){
		ComplexListNode *pClone = new ConplexListNode();
		pClone->value = pNode->value;
		pClone->pNext = pNode->pNext;

		pNode->pNext = pClone;
		pNode = pClone->pNext;
	}
}


复制完结点后,接下来需要设置每个新结点的 pSibling。假设原始链表中结点N指向的pSibling为S, 那么对应的结点N‘ 指向的pSibling也为S’。故完成这步的代码如下所示:

void  ConnectSiblingNodes( ComplexListNode *pHead ){
	ComplexListNode *pNode = pHead;
	while( pNode != NULL ){
		ComplextListNode *pClone = pNode->pNext;
		if( pNode->pSibling != NULL ){
			pClone->pSibling = pNode->pSibling->mNext;
		}
		pNode = pClone->pNext;
	}
}


完成上面两步后,现在的链表是有原始链表和复制链表组合而成的,因此现在可以通过奇偶位来得到复制的链表,实现代码如下:

ComplexListNode*  ReconnectListNode( ComplexListNode* pHead ){
	ComplexListNode *pNode = pHead;
	ComplexListNode *pCloneHead = NULL;
	ComplexListNode *pCloneNode = NULL;

	if( pNode != NULL ){
		pCloneHead = pCloneNode = pNode->pNext;
		pNode = pCloneNode->pNext;
		
		while( pNode != NULL ){
			pCloneNode->pNext = pNode->pNext;
			pCloneNode = pCloneNode->pNext;
			pNode = pCloneNode->pNext;
		}
	}
	return pCloneHead;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: