链表面试题(进阶)&&复杂链表的复制
来源:互联网 发布:rgb转化到hsv的算法 编辑:程序博客网 时间:2024/06/16 06:12
单链表面试题(进阶)
1、判断单链表是否带环?若带环,求环的长度?求环的入口点?
2、判断两个链表是否相交,若相交,求交点。(假设链表不带环)
3、判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
//ps: 复杂链表的结构
struct ComplexNode
{
int _data ; // 数据
struct ComplexNode * _next; // 指向下一个节点的指针
struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
};
1、判断单链表是否带环?若带环,求环的长度?求环的入口点?
在链表的头结点定义一个快指针和慢指针,让慢指针一次走两步,快指针一次走两步,如果链表带环,则快指针一定会追上慢指针的,如果不带环则快指针先到表尾。若是求环的长度时,在快指针和慢指针在环内相交时,记住这个点,然后让慢指针从这个点开始再走一圈,即可求出环的长度。
ListNode *check_Ring(ListNode *plist)
{//1、空或者只有一个 2、带环链表 3、不带环
if(plist == NULL && plist->next == NULL)
{
printf("不带环\n");
return 0;
}
else
{
ListNode *slow = plist;
ListNode *fast = plist;
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if(slow == fast)
return slow;
}
return NULL;
}
}
Datatype LengthList(ListNode *plist)
{//求环长读。先求慢节点的位置,然后让慢节点走一圈就是环的长度
assert(plist);
if(plist->next == NULL)
return 1;
else
{
ListNode *slow = check_Ring(plist);
ListNode *next = slow->next;
int step = 1;
while(slow != next)
{
step++;
next = next->next;
}
return step;
}
}
求环的入口点,可以由下面的公式求
ListNode *InRingNode(ListNode *plist)
{//要是环至少得有两个及以上的节点
if(plist == NULL && plist->next == NULL)
return NULL;
else
{
ListNode *fast = check_Ring(plist);;
while(plist != fast)
{
plist = plist->next;
fast = fast->next;
}
return plist;
}
}
2、判断两个链表是否相交,若相交,求交点。(假设链表不带环)
先让两个链表遍历一遍分别求出尾指针,如果不相同则不相交,相同则分别求出两个链表的长度,然后让长的先走他们的长度之差步,然后再一起走,若走到节点相同时就是交点。
ListNode *FindpointList(ListNode *plist1, ListNode *plist2)
{
assert(plist1 && plist2);
ListNode *tail1 = plist1;
ListNode *tail2 = plist2;
int i = 1;
int j = 1;
while(tail1->next)//先遍历链表求长度
{
tail1 = tail1->next;
++i;
}
while(tail2->next)
{
tail2 = tail2->next;
++j;
}
if(tail1 != tail2)//如果两个尾指针相同则在往前找交点
return NULL;
else
{
int num = abs(i-j);
if(i >= j)//哪个长度大,哪个就先走
{
while(num--)
{
plist1 = plist1->next;
}
}
else
{
while(num--)
{
plist2 = plist2->next;
}
}
while(plist1 != plist2)//当两个节点相同时就是交点
{
plist1 = plist1->next;
plist2 = plist2->next;
}
return plist1;
}
}
3、判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
判断两个可能带环的链表相交问题,先分析清楚有几种可能性然后再求
1、1、两个连表达不带环(这种情况已经分析)
2、一个链表带环,另一个不带环
3、两个链表都带环
3.1、两个不想交
3.2、有一个交点在环外
3.3、两个交点在环内
ListNode *IsCrossList(ListNode *plist1, ListNode *plist2)
{
//1、两个连表达不带环(这种情况已经分析)
//2、一个链表带环,另一个不带环
//3、两个链表都带环
// 3.1、两个不想交
// 3.2、有一个交点在环外
// 3.3、两个交点在环内
assert(plist1);
assert(plist2);
ListNode *list1 = check_Ring(plist1);
ListNode *list2 = check_Ring(plist2);
if((list1 != NULL && list2 == NULL) || ((list1 == NULL) && (list2 != NULL)))
{//若两个链表一个带环一个不带环则不相交
return NULL;
}
if(list1 != NULL && list2 != NULL)
{
ListNode *cur1 = InRingNode(plist1);
ListNode *cur2 = InRingNode(plist2);
if(cur1 == cur2)//若交点相同则在环外相交
{
ListNode *slow = list1;
slow->next = NULL;
ListNode *plist = FindpointList(plist1, plist2);
return plist;
}
else//交点不相同则在环内
{
Datatype num = LengthList(plist1);
ListNode *tmp = cur1;
while(--num)//当一圈走完都没有发现另一个入口点,那就是不相交
{
while(tmp != cur2)
{
tmp = tmp->next;
}
return cur1;
}
}
}
return NULL;
}
4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
//ps: 复杂链表的结构
struct ComplexNode
{
int _data ; // 数据
struct ComplexNode * _next; // 指向下一个节点的指针
struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
};
用以下步骤来实现复杂链表的复制
1、先创建一个和每个节点都相同的节点
2、按顺序的将这些节点依次插到和它数据相同节点的后面,然后全部连接起来
3、操作这些“复制后”的节点,让每个节点的随机节点指向原节点的随机节点的下一位
4、分离复制的链表和原链表,返回复制后的链表
typedef struct ComplexNode
{
Datatype _data ; // 数据
ComplexNode * _next; // 指向下一个节点的指针
ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
}ComplexNode;
ComplexNode *buyNode(Datatype h)
{
ComplexNode *node = (ComplexNode *)malloc(sizeof(ComplexNode));
assert(node);
node->_data = h;
node->_next = NULL;
node->_random = NULL;
return node;
}
ComplexNode *CopyList(ComplexNode *plist)//复制链表
{
ComplexNode *cur = plist;
if(plist == NULL && plist->_next == NULL)
return NULL;
while(cur)//将创造的和前一个节点相同的节点全都连起来
{
ComplexNode *next = plist->_next;
ComplexNode *tmp = buyNode(cur->_data);
tmp->_next = cur->_next;
cur->_next = tmp;
cur = tmp->_next;
}
ComplexNode *newlist = plist;
ComplexNode *tail = NULL;
while(newlist != NULL)
{
ComplexNode *newcur = newlist->_next;
if(newlist->_random != NULL)
newcur->_random = newlist->_random->_next;
newlist = newcur->_next;
}
return plist;
}
ComplexNode *DetachList(ComplexNode *plist)//分离复制后的节点
{
ComplexNode *newlist = plist;
ComplexNode *next = newlist->_next;
ComplexNode *head = next;
if(newlist)
{
newlist->_next = next->_next;
newlist = newlist->_next;
}
while(newlist)
{
next->_next = newlist->_next;
next = next->_next;
newlist->_next = next->_next;
newlist = newlist->_next;
}
return head;
}
阅读全文
0 0
- 链表面试题(进阶)&&复杂链表的复制
- 链表面试题之复杂链表的复制
- 单链表面试题--复杂链表的复制
- 链表面试题之复杂链表的复制
- 链表面试题总结----(可能带环相交问题+复杂链表的复制)
- 链表面试题 进阶
- 【C】单链表面试题(进阶)
- 链表面试题 进阶 二
- 【面试题】复杂链表的复制
- 面试题:复杂链表的复制
- C语言 — 链表面试题复杂链表问题
- C语言的单链表面试题----进阶
- 常见的单链表面试题——进阶篇
- C语言实现单链表面试题(进阶篇)
- 程序员面试题精选---复杂链表的复制
- 面试题26:复杂链表的复制
- [剑指offer][面试题26]复杂链表的复制
- 剑指offer 面试题26复杂链表的复制
- 【Python】Macbook Pro MacOS Sierra 无法加载 matplotlib.pyplot 解决办法
- js刷新
- Android Studio混淆模板
- ssm(springmvc4+spring4+mybatis3)整合实战-个人博客系统-dao与service层等组件整合
- ARM中断处理流程
- 链表面试题(进阶)&&复杂链表的复制
- 用户增删改查:在eclipse创建Spring+SpringMVC+Mybatis的项目
- Linux Mint 15下载安装以及配置环境(6/16)
- SqlServer性能优化用SQL(二)【索引监控】
- 使div水平居中的方式
- 内联函数的优缺点
- 杭电 1846Brave Game(巴什博弈)
- Git分支-分支的新建和合并(实践)
- Android NDK网络通信篇(五)之TCP通信篇