略有所悟:不一定总是从头到尾一气呵成,像这样的一个节点一个节点的复制,先合成一个整体,之后在分开也是复制。关键是这样省去了寻找复制节点的时间(因为每当复制当前节点时一定要找到原来父节点所在的位置)。
思路如下:
在不用辅助空间的情况下实现O(n)的时间效率。第三种方法的第一步仍然是根据原始链表的每个结点N,创建对应的N’。这一次,我们把N’链接在N的后面。实例中的链表经过这一步之后变成了:
这一步的代码如下:
/////////////////////////////////////////////////////////////////////////////////
// Clone all nodes in a complex linked list with headpHead,
// and connect all nodes with m_pNext link
/////////////////////////////////////////////////////////////////////////////////
void CloneNodes(ComplexNode* pHead)
{
ComplexNode* pNode = pHead;
while(pNode!= NULL)
{
ComplexNode* pCloned = new ComplexNode();
pCloned->m_nValue = pNode->m_nValue;
pCloned->m_pNext = pNode->m_pNext;
pCloned->m_pSibling = NULL;
pNode->m_pNext = pCloned;
pNode = pCloned->m_pNext;
}
}
第二步是设置我们复制出来的链表上的结点的m_pSibling。假设原始链表上的N的m_pSibling指向结点S,那么其对应复制出来的N’是N->m_pNext,同样S’也是S->m_pNext。这就是我们在上一步中把每个结点复制出来的结点链接在原始结点后面的原因。有了这样的链接方式,我们就能在O(1)中就能找到每个结点的m_pSibling了。例子中的链表经过这一步,就变成如下结构了:
这一步的代码如下:
/////////////////////////////////////////////////////////////////////////////////
// Connect sibling nodes in a complex link list
/////////////////////////////////////////////////////////////////////////////////
void ConnectSiblingNodes(ComplexNode* pHead)
{
ComplexNode* pNode = pHead;
while(pNode!= NULL)
{
ComplexNode* pCloned = pNode->m_pNext;
if(pNode->m_pSibling != NULL)
{
pCloned->m_pSibling =pNode->m_pSibling->m_pNext;
}
pNode = pCloned->m_pNext;
}
}
第三步是把这个长链表拆分成两个:把奇数位置的结点链接起来就是原始链表,把偶数位置的结点链接出来就是复制出来的链表。上述例子中的链表拆分之后的两个链表如下:
要实现这一步,也不是很难的事情。其对应的代码如下:
/////////////////////////////////////////////////////////////////////////////////
// Split a complex list into two:
// Reconnect nodes to get the original list, and itscloned list
/////////////////////////////////////////////////////////////////////////////////
ComplexNode* ReconnectNodes(ComplexNode* pHead)
{
ComplexNode* pNode = pHead;
ComplexNode* pClonedHead = NULL;
ComplexNode* pClonedNode = NULL;
if(pNode!= NULL)
{
pClonedHead = pClonedNode =pNode->m_pNext;
pNode->m_pNext = pClonedNode->m_pNext;
pNode = pNode->m_pNext;
}
while(pNode!= NULL)
{
pClonedNode->m_pNext = pNode->m_pNext;
pClonedNode = pClonedNode->m_pNext;
pNode->m_pNext = pClonedNode->m_pNext;
pNode = pNode->m_pNext;
}
return pClonedHead;
}
我们把上面三步合起来,就是复制链表的完整过程:
/////////////////////////////////////////////////////////////////////////////////
// Clone a complex linked list with head pHead
/////////////////////////////////////////////////////////////////////////////////
ComplexNode* Clone(ComplexNode* pHead)
{
CloneNodes(pHead);
ConnectSiblingNodes(pHead);
return ReconnectNodes(pHead);
}
// 程序员面试题精选100题(49)-复杂链表的复制.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
#define N 6
struct ComplexNode
{
char m_nValue;
ComplexNode* m_pNext;
ComplexNode* m_pSibling;
};
ComplexNode* constructList()//according to the next
{
char ch;
int i=0;
ComplexNode* head=NULL,*p=NULL,*q=NULL;
cout<<"construct list next"<<endl;
while(i<N)
{
cin>>ch;
if (head==NULL)
{
head = new ComplexNode;
head->m_nValue=ch;
head->m_pNext=NULL;
head->m_pSibling=NULL;
p=head;
}
else
{
q = new ComplexNode;
q->m_nValue=ch;
q->m_pNext=NULL;
q->m_pSibling=NULL;
p->m_pNext=q;
p=p->m_pNext;
}
i++;
}
return head;
}
ComplexNode* constructListSibling(ComplexNode* head)// build the list need o(n*n) time. how to build the complex list within time of o(n),
{
char ch1,ch2;
int i=0;
ComplexNode *p,*q;
cout<<"construct list sibling"<<endl;
while(i<N)
{
cin>>ch1;cin>>ch2;
p=head;q=head;
while(p&&p->m_nValue!=ch1)p=p->m_pNext;
while(q&&q->m_nValue!=ch2)q=q->m_pNext;
if (p&&q)//both are not Null
{
p->m_pSibling=q;
}
i++;
}
return head;
}
void printListNext(ComplexNode* head)
程序员面试题精选100题(49)-复杂链表的复制
时间:2019-09-22
- 私立学校怎样面试?参考这些真题做好准备(天府第七中学面试题)
- 成都市2017小升初私立学校面试攻略和去年真题汇总
- 广州2017年公办小学面试
- 程序员面试题精选100题(63)-数组中三个只出现一次的数字
- 程序员面试题精选100题(62)-C/C++/C#面试题(5)
- 程序员面试题精选100题(61)-数对之差的最大值[算法]
- 程序员面试题精选100题(60)-判断二叉树是不是平衡[数据结构]
- 程序员面试题精选100题(59)-字符串的组合[算法]
本文已影响
人好书推荐
最新文章
推荐文章
推荐栏目
- 剧情介绍
- 早晚安心语
- 初中学习方法
- 教育资讯
- 办公表格
- 论文大全
- 理财知识
- 高中学习方法
- 简历下载
- 路由器
- 脑力开发
- 放假安排
- 作文大全
- 读后感
- 介绍信
- 感谢信
- 承诺书
- 节日大全
- Office教程
- 述职报告
- 标语
- 评语
- 合同范本
- 情书
- 请假条
- 责任书
- 请示
- 感言
- 方案大全
- 常用证明
- 口号
- 观后感
- 自我介绍
- 常识
- 弟子规
- 倡议书
- 日记
- 句子大全
- 大学
- 美文
- 职场顾问
- 唐诗
- 党团范文
- 语文
- 申请书
- 课件
- 历史故事
- 主题班会
- 调研报告
- 经典台词
- 说说大全
- 编程笔记
- 歇后语
- 自我评价
- 通知
- 应急预案
- 广告语
- 三字经
- 规章制度
- 邀请函
- 检讨书
- 委托书
- 加油稿
- 工作计划
- 实习范文
- 教案
- 工作总结
- 社保
- 政策法规
- 员工手册
- 讲话致辞
- 求职面试
- 辞职报告
- 自我鉴定
- 心得体会
- 社会实践报告
- 岗位职责
- 周公解梦
- 事迹材料