您的位置:首页 > 职场人生

面试题26:复杂链表的复制

2016-07-03 20:20 375 查看
       题目:复制一个复杂链表。在复杂链表中,每个节点除了有一个next指针指向下一个节点外,还有一个指针指向链表中的任意节点或者NULL。

       这道题之前从未见过。一开始反应是先按照正常的链表复制方法。也就是只有next指针的链表。然后再重新遍历一遍,复制链表的另外一个指针。但是,要考虑寻找一个已知的链表节点的时间复杂度是O(n),必须从头往后遍历。也就使得整个算法的时间复杂度是O(n*n).这显然复杂度太高了。

      看了下书上的解释,想着维护一个map,记录每个节点的另外一个指针,待复制后,直接取出指向它即可。这相当于用空间复杂度去换取时间复杂度。用O(n)的空间复杂度使得算法的时间复杂度由O(n*n)编程O(n),一般来说这就是比较理想的了,毕竟现在内存这么便宜。然而书上还有另外一个方法,不需要O(n)空间复杂度,也可以o(n)时间,简直逆天了,方法如下:

        struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};

class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(pHead==NULL)
return pHead;
RandomListNode *tempNode=pHead;
cloneNode(tempNode);
connectRandom(tempNode);
return pickDump(tempNode);
}
void cloneNode(RandomListNode* headNode)
{
RandomListNode *pHead=headNode;
while(pHead)
{
RandomListNode *newNode=new RandomListNode(0);
newNode->label=pHead->label;
newNode->next=pHead->next;
newNode->random=NULL;
pHead->next=newNode;
pHead=newNode->next;
}
}
void connectRandom(RandomListNode* headNode)
{
RandomListNode *pHead=headNode;
while(pHead)
{
if(pHead->random!=NULL)
{
pHead->next->random=pHead->random;
}
pHead=pHead->next->next;
}
}
RandomListNode* pickDump(RandomListNode* pHead)
{
RandomListNode *newHead;
RandomListNode *oldNode=pHead;
if(oldNode)
{
newHead=oldNode->next;
oldNode->next=newHead->next;
oldNode=oldNode->next;
}
RandomListNode *curNode=newHead;
while(oldNode)
{
curNode->next=oldNode->next;
curNode=curNode->next;
oldNode->next=curNode->next;
oldNode=oldNode->next;
}
return newHead;
}
};       总共分三步来处理,第一步,复制节点,并且把复制节点分别插入到每个待复制节点的后面。第二步,都插另外一个指针。第三步,将链表分离成两个链表。一个之前的,一个是复制的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: