复杂链表的复制
2011-11-10 20:06
369 查看
精选软件工程师面试题-复杂链表的复制
(2011-02-28 21:06:55)
转载
structComplexNode
{
int m_nValue;
ComplexNode* m_pNext;
ComplexNode* m_pSibling;
};
下图是一个含有5个结点的该类型复杂链表。图中实线箭头表示m_pNext指针,虚线箭头表示m_pSibling指针。为简单起见,指向NULL的指针没有画出。
请完成函数ComplexNode*Clone(ComplexNode* pHead),以复制一个复杂链表。
分析: 此题目已经有很多人在blog上做过分析, 我没有一个比较精练的, 在次我描述出我的想法. 仅供参考.
这个题目的难点在于如何对m_pSibling指针复制,使新的列表具有和原列表同样的结构.
如原列表是ABCDE,Clone列表是abcde.
难点在于:如何复制虚线部分的指针.
[align=left]其实有个很巧妙的方法, 给A,B,C,D,E编号,分别为0,1,2,3,4.如果所示. 这样m_pSibling的clone就很简单.[/align]
[align=left]Forexample:[/align]
[align=left] 节点 b 对应的是原节点B, B->m_pSibling 是E, E的编号是4.这样新列表的第4个节点的地址赋给b->m_pSibling就可以了.[/align]
[align=left]但关键一点是原列表每个节点的编号保存在哪呢?如果编号没有地方保存, 也不能降低clone的复杂度. 我们注意到没每个节电有一个m_nValue成员, 我们可以利用它来做文章.即首先把每个节电的m_nValue备份出来, 临时用来保存编号, 等clone完成后, 再restore.[/align]
[align=left]同时还要把a,b,c.d,e的地址也按顺序保存在一个数组里,以方便获取他们的地址.[/align]
[align=left] [/align]
[align=left]这样这个算法就很简单了,只对原列表遍历两次就可以完成复制, 时间复杂度为O(2n):[/align]
[align=left]备份原列表每个节点的m_nValue 到数组backupValue. 同时分别设置他们为所在节点的序号值.[/align]
[align=left]由原列表 clone出新列表(只设置每个接点的m_pNext值). 新列表每个节点的m_pSibling 置为 NULL.同时新列标的每个节点地址按顺序保留到数组newListAddrees中.[/align]
[align=left]Clone m_pSibling:从原列表取一个节点, 如果此节点的m_pSibling为NULL, 取下一个.假设此节点为M. 由M->m_nValue 找到 m(newListAddrees[M->m_nValue]). 并设置m_pSibling:newListAddrees[M->m_nValue]->m_pSibling=newListAddrees[M->m_pSibling->m_nValue].直到原列表的节点的m_pSibling全复制完.[/align]
[align=left]由backupValue恢复原列表的m_nValue.[/align]
[align=left]设置新列表的m_nValue.[/align]
[align=left]代码: [/align]
ComplexNode* CloneList(ComplexNode* pHead)
{
ComplexNode* pNode = pHead;
ComplexNode** ppBackupNewList;
int nTotal = 0;
int i = 0;
while(pNode)
{
nTotal++;
pNode = pNode->m_pNext;
}
ppBackupNewList = (ComplexNode **)malloc(sizeof(ComplexNode *)*nTotal);
pNode = pHead;
while(pNode != NULL)
{
ppBackupNewList[i] = (ComplexNode *)malloc(sizeof(ComplexNode));
if (i > 0)
ppBackupNewList[i - 1]->m_pNext =ppBackupNewList[i];
ppBackupNewList[i]->m_pSibling = NULL;
ppBackupNewList[i]->m_nValue =pNode->m_nValue;
pNode->m_nValue = i++;
pNode = pNode->m_pNext;
}
ppBackupNewList[nTotal - 1]->m_pNext = NULL;
pNode = pHead;
while(pNode != NULL)
{
if (pNode->m_pSibling)
ppBackupNewList[pNode->m_nValue]->m_pSibling=
ppBackupNewList[pNode->m_pSibling->m_nValue];
pNode = pNode->m_pNext;
}
i = 0;
pNode = pHead;
while(pNode != NULL)
{
pNode->m_nValue =ppBackupNewList[i++]->m_nValue;
pNode = pNode->m_pNext;
}
pNode = ppBackupNewList[0];
free(ppBackupNewList);
return pNode;
}
相关文章推荐
- 复杂链表的复制(C++)
- 复杂链表的复制
- 剑指offer——复杂链表的复制
- 转载:程序员面试题精选100题(49)-复杂链表的复制
- 剑指offer--复杂链表的复制
- 剑指offer复杂链表复制
- 剑指offer-25-js-复杂链表的复制
- 复杂链表的复制
- 【剑指offer】复杂链表的复制
- 【剑指offer】复杂链表的复制
- 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序
- 剑指OFFER之复杂链表的复制(九度OJ1524)
- 剑指offer——复杂链表的复制(还不错,空间优先法和时间优先法)
- 分解让复杂问题简单化:复杂链表的复制
- 链表面试题-复杂链表的复制
- 复杂链表的复制
- 复杂链表的复制
- 复杂链表的复制
- 复杂链表的复制
- 138. Copy List with Random Pointer&复杂链表的复制