剑指offer面试题26:复杂链表的复制
题目 :
复杂链表的结点的定义如下:
//链表的结点的定义为:
struct ComplexListNode
{
int val ; //结点内保存的值
ComplexListNode* my_pNext; //节点的next指针
ComplexListNode* my_pSibling; //表示的是随机指针
ComplexListNode(const int value)
:val(value)
,my_pSibling(NULL)
,my_pNext(NULL)
{}
};
复杂链表的结构实体图:
对于这样的题目 ,很多的人的第一思路 就是分成的两步:
1、先复制链表的结点,并使用next指针链接起来;
2、在 设置每一个结点的随机指针。
但是这种方法,在设置结点随机指针的 过程中 ,要先遍历一遍 链表找随机指针在链表的指向的位置 ,
那么,每一个结点都这么找一下话,那么这个函数的时间复杂度 ,就是O(N
);
要是面试的时候,你被问到的是这个题目,你这要回答,那么面试官肯定不会满意的。。
一句话,再好好想想吧!!!
在这里就交给你一种简单的方法,来解决这种复杂问题的复制:
1、将新复制的每一个结点的连接到源结点的后面 ,(先不管随机指针);
2、设置复制后的结点的随机指针;
但是要怎么来设置呢???(经典的地方)
如果仔细看的话 ,,我们就会发现,随机指针的指向,就是原结点的随机指针的next结点(NULL除外
)
3、指针设置好后,那么就要断开连接,得到复制后的链表的头结点
实现的结果:
代码实现:
//面试题26 :复杂李彪链表的复制
//链表的结点的定义为:
struct ComplexListNode
{
int val ; //结点内保存的值
ComplexListNode* my_pNext; //节点的next指针
ComplexListNode* my_pSibling; //表示的是随机指针
ComplexListNode(const int value)
:val(value)
,my_pSibling(NULL)
,my_pNext(NULL)
{}
};
//要实现这个问题的话 ,要是么有什么限制的话,那是很简单的;
//但是这个样子是很难闹到offer的;
ComplexListNode* CopyComplexList(ComplexListNode* head)
{
ComplexListNode* ret = NULL;//使用的是 ret表示的是 要返回的复制后的链表后的结点
if(head == NULL)
return ret;//表示的是 当原有的链表为 空的话 ,那么直接返回的kong;
//先建立新的结点连接到 当前的结点后面 ,,,方便 随机指针的链接
// 1、 第一步代码 ************
ComplexListNode* cur = head;
while(cur)
{
ComplexListNode * node = new ComplexListNode(cur->val);//先用当前的结点的值 复制一个结点连接到当前节点的后面
//链接
node->my_pNext = cur->my_pNext;
cur->my_pNext = node;
cur = node->my_pNext;
}
// 2、 第二步代码 ************
//链接完成后 就到了链接 随机指针
cur = head;
while(cur)
{
//node表示的是新生成的结点
ComplexListNode* node = cur->my_pNext;
//链接随机指针
if(cur->my_pSibling)//这个判断很重要的
node->my_pSibling = cur->my_pNext->my_pNext;
cur = node->my_pNext;
}
// 3、 第三步代码 ************
//断开连接
cur = head;
ComplexListNode* prev = NULL;
while(cur)
{
//node表示的是新生成的结点
ComplexListNode* node = cur->my_pNext;
cur ->my_pNext = node->my_pNext;
cur = cur->my_pNext;
if(prev)
{
prev->my_pNext = node;
ret = node;
}
prev = node;
}
return ret;
}