链表相关笔试面试题

1.判断两个链表是否相交

    两个链表是否相交可分为以下几种情况
    (1)两个链表都不带环,此时两个链表所对应的最后一个节点是相等的
    (2)两个链表一个带环,一个不带环,两个链表一定不相交
    (3)连个链表都带环,如果相交则可以分为以下三种情况
      1)两个链表在环外相交, 此时链表1 和链表2 对应的环的入口地址是相等的
      2)两个链表在换上相交,此时从一个环的入口地址出发,一定可以到达另一个环的入口
      3)如果不是以上两种情况,则连个链表一定不相交

/***链表是否相交没有环 **/int LinkListHasCrossWithCircle(LinkNode* head1, LinkNode* head2)
{if(head1 == NULL || head2 == NULL){return 0;}LinkNode* cur1 = head1;while(cur1 -> next != NULL){cur1 = cur1 -> next;}LinkNode* cur2 = head2;while(cur2 -> next != NULL){cur2 = cur2 -> next;}if(cur1 == cur2){return 1;}return 0;
}   /*** 链表是否相交,不确定有没有环 **/int LinkListHasCrossWithCircle2(LinkNode* head1, LinkNode* head2)
{if(head1 == NULL || head2 == NULL){return 0;//两链表至少一个为空}                                                                                                                                                          LinkNode* circle1 = LinkListHasCircle(head1);LinkNode* circle2 = LinkListHasCircle(head2);//两个链表都不带环if(circle1 == NULL && circle2 == NULL){return LinkListHasCrossWithCircle(head1, head2);}//两链表都带环else if(circle1 != NULL && circle2 != NULL){//在环外相交LinkNode* entry1 = LinkListGetCircleEntry(head1);LinkNode* entry2 = LinkListGetCircleEntry(head2);if(entry1 == entry2){return 1;}//再换上相交else if(entry1 != entry2){LinkNode* cur1 = entry1;//从一个环入口点出发可以到达另外一个环入口点,则证明相交while(cur1 != entry2){cur1 = cur1 -> next;}return 1;}//不是上述情况则没有相交return 0;}//一个带环一个不带环,则一定不相交else if( ( circle1 == NULL && circle2 != NULL )|| (circle1 != NULL && circle2 == NULL)){return 0;}
}

                       这里写图片描述

2.求链表的交点

    求换的交点和上述判断是否有环是一个思路,可以分为一下几种情况
    (1)两个链表都不带环的情况下,先利用上面的函数判断出连个链表是否相交,再求出两个链表的长度 size1, size2,再将两个链表的长度做差(长的减短的)得到一个大于等于0 的数 offset,再让分别定义两个指针 cur1, cur2, 指向 head1, head2, 然后让长链表对应的 cur1(假定cur1所指的链表长) 先走 offset 步,cur2 不动,cur1 每走一步 offset 就减1, 等到 offset 等于 0 的时候这个时候就说明两个指针cur1, cur2 都相对于交点的距离相等, 这个时候让 cur1, cur2 一起向后走,当它们两个指针所对应的节点相同时, 此时这个相同的节点就是两个链表的交点
    (2)当两个链表一个带环,一个不带环时, 此时链表一定不相交,直接返回空
    (3)当两个链表都有环时,分为一下三种情况
      1)两个链表在环外相交,此时的交点求法如图所示

     这里写图片描述
      2)连个链表在环上相交
                         这里写图片描述
      3)如果不是以上两种,那么一定不相交

/**                                                                                                                                                             *环的相交点不带环**/LinkNode* LinkListCrossPoint(LinkNode* head1, LinkNode* head2)
{if(head1 == NULL || head2 == NULL){return NULL;//两链表至少一个为空}int len1 = LinkListSize(head1);int len2 = LinkListSize(head2);LinkNode* cur1 = head1;LinkNode* cur2 = head2;int offset = 0;if(len1 > len2){offset = len1 - len2;for(; offset > 0; cur1 = cur1 -> next){offset--;}}else if(len2 > len1){offset = len2 - len1;for(; offset > 0; cur2 = cur2 -> next){offset--;}}for(; cur1 != cur2; cur1 = cur1 -> next, cur2 = cur2 -> next){;}return cur1;                                                                                                                                               
}/**                                                                                                                                                             *环的相交点带环不带环不确定**/LinkNode* LinkListCrossPoint2(LinkNode* head1, LinkNode* head2)
{if(head1 == NULL || head2 == NULL)                                                                                                                       {    return NULL;//两链表至少一个为空,一定不相交}    LinkNode* entry1 = LinkListGetCircleEntry(head1);LinkNode* entry2 = LinkListGetCircleEntry(head2);//如果两个都不带环,直接用第一个版本if(entry1 == NULL && entry2 == NULL){    return LinkListCrossPoint(head1, head2);}    //如果一个带环,一个不带环,一定不相交if(( entry1 == NULL && entry2 != NULL ) || ( entry1 != NULL && entry2 == NULL )){    return NULL;}    //如果两个都有环LinkNode* cur1 = head1;LinkNode* cur2 = head2;if(entry1 != NULL && entry2 != NULL){    
//环外相交if(entry1 == entry2){LinkNode* end = entry1;int size1 = 0;int size2 = 0;for(; cur1 != end; cur1 = cur1 -> next){size1++;}size1 = size1 + 1;for(; cur2 != end; cur2 = cur2 -> next){size2++;}size2 = size2 + 1;int offset =  0;if(size1 > size2){offset = size1 - size2;                                                                                                                      for(cur1 = head1, cur2 = head2; offset > 0; offset--){cur1 = cur1 -> next;}for(; cur1 != end && cur1 != cur2; cur1 = cur1 -> next, cur2 = cur2 -> next){;}return cur1;}else if(size2 > size1){offset = size2 - size1;for(cur1 = head1, cur2 = head2; offset > 0; offset--){cur2 = cur2 -> next;}for(; cur1 != end && cur1 != cur2; cur1 = cur1 -> next, cur2 = cur2 -> next){;}return cur1;}else//size1  = size2{for(cur1 = head1, cur2 = head2; cur1 != cur2 && cur1 != end && cur2 != end; cur1 = cur1 -> next, cur2 = cur2 -> next){                                                                                                                                            ;}return cur1;}}//环内相交,相交点就是入口else if(entry1 != entry2){LinkNode* cur = entry1;for(; cur != entry2; cur = cur -> next){;}return entry2;cur = entry2;for(; cur != entry1; cur = cur -> next){;}return entry1;}//不是上述两种情况,则不相交else{return NULL;}                                                                                                                                                    }
}

                这里写图片描述

3.求连个链表的交集

    求交集就是分别定义两个指针 cur1, cur2,指向两个对应的链表的首元素, 然后将 cur1 和 cur2 所指的链表的 data 进行比较, 如果相等, 将这个结点插入到一个新链表中, 然后两个指针 cur1, cur2, 一起向后走一步,如果不相等, 就将 data 值小的那个指针向后移动, 而另外一个指针不动, 在进行比较,重复以上动作,直到 cur1 或者 cur2 两个中其中一个为空,则停止循环

LinkNode* LinkListUnionSet(LinkNode* head1, LinkNode* head2)
{if(head1 == NULL || head2 == NULL){return NULL;//两个链表至少有一个为空}LinkNode* cur1 = head1;LinkNode* cur2 = head2;LinkNode* new_head = NULL;LinkNode* new_tail = NULL;while(cur1 != NULL && cur2 != NULL){if(cur1 -> data < cur2 -> data){cur1 = cur1 -> next;}else if(cur1 -> data > cur2 -> data){cur2 = cur2 -> next;}else{if(new_head == NULL){new_head = LinkNodeCreat(cur1 -> data);new_tail = new_head;}else{new_tail -> next = LinkNodeCreat(cur1 -> data);new_tail = new_tail -> next;}cur1 = cur1 -> next;                                                                                                                               cur2 = cur2 -> next;}}return new_head;
}

这里写图片描述

4. 拷贝复杂链表

    先看一下复杂链表的数据结构

typedef struct ComplexNode
{LinkNodeType data;struct ComplexNode* next;struct ComplexNode* random;
}ComplexNode;

    复杂链表中除了 data, next, 之外,还有一个 random, 它可能指向链表中的如何一个节点, 还可能指向空。
    在进行复杂链表的拷贝时, 可以采用下面的方法, 先将复杂链表按照简单链表进行复制,将其复制到一个新链表中, 此时的新链表还是一个简单链表, 然后再遍历旧链表,求出每一个节点所对应的 random 相对于头节点的偏移量, 再遍历新链表, 根据所求得的偏移量确定新链表中的 random 的指针的指向。

/*** 复杂链表的拷贝**/                                                                                                                                                            ComplexNode* ComplexCopy(ComplexNode* head)
{if(head == NULL){return NULL;//空链表}ComplexNode* cur = head;ComplexNode* new_head = NULL;ComplexNode* new_tail = NULL;while(cur != NULL){if(new_head == NULL){new_head = head ;new_tail = new_head;}else{new_tail -> next = cur;new_tail = new_tail -> next;}cur = cur -> next;}//求每个random相对于头结点的偏移量int offset = 0;ComplexNode* new_cur = new_head;for(cur = head; cur != NULL; cur = cur -> next,new_cur = new_cur -> next){//求出每个结点相对于head的偏移量offset = Diff(head, cur -> random);//修改新链表中的random的值new_cur -> random = Step(new_head, offset);}return new_head;
}/*                                                                                                                                                             ** 通过offset找到random**/ComplexNode* Step(ComplexNode* head, int offset)
{if(head == NULL){    return NULL;//空链表}    if(offset == -1){    return NULL;}    ComplexNode* cur = head;ComplexNode* random = head;//让 random 走 offset 步,再将 cur -> random = randomfor(; offset > 0; offset --){    random = random -> next;}    return random; 
}/*** 求出每个结点相对于head的偏移量**/int Diff(ComplexNode* head, ComplexNode* random)
{if(head == NULL){return -2;}if(random == NULL){return -1;}ComplexNode* cur = head;ComplexNode* new_cur = random;int count = 0;while(cur != new_cur){count++;cur = cur -> next;}return count;
}

这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384097.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux经典问题—五哲学家就餐问题

http://m.blog.csdn.net/aspenstars/article/details/70149038 一、问题介绍 由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。该问题是描述有五个哲学家共用一张圆桌&#xff0c;分别坐在周围的五张椅子上&#xff0c;在圆桌上有五…

修改之前的myshell使之支持输入输出重定向

1.open函数     这个函数是打开一个文件&#xff08;文件名叫pathname),以 flag 权限打开&#xff0c;flag 包括了以下几种 O_RDONLY&#xff08;只读&#xff09;, O_WRONLY&#xff08;只写&#xff09;, O_RDWR&#xff08;读写&#xff09;&#xff0c;当文件打开成…

HDU - 6621 K-th Closest Distance——主席树+二分

【题目描述】 HDU - 6621 K-th Closest Distance 【题目分析】 因为看到第kkk大的要求&#xff0c;刚开始的时候一直都在想怎么运用第kkk大来解决问题&#xff0c;但是后来看其他人的博客才发现并不需要用第k大&#xff0c;但是主席树维护权值线段树还是需要的&#xff0c;这…

链表相关的算法题大汇总 — 数据结构之链表奇思妙想

http://blog.csdn.net/lanxuezaipiao/article/details/22100021基本函数&#xff08;具体代码实现见后面&#xff09; 1&#xff0c;构造节点 //定义节点类型 struct Node { int value; Node*next; }; 2&#xff0c;分配节点 //之所以要分配节点原因是需要在分配函数中…

CodeForces - 372CWatching Fireworks is Fun+DP+单调队列优化

【题目描述】 CodeForces - 372CWatching Fireworks is Fun 题目的大概意思就是在一个编号为1…n的街道上现在按照时间顺序放烟花&#xff0c;每个烟花获得的幸福感为b−abs(a−x)b-abs(a-x)b−abs(a−x)&#xff0c;x为观看烟花的位置&#xff0c;为了提升我们的幸福感&#x…

双向链表的基本操作

1.双向链表的数据结构 typedef char DLinkType;typedef struct DLinkNode { DLinkType data; struct DLinkNode* next; struct DLinkNode* prev; }DLinkNode; 双向带头结点的链表有三个成员&#xff0c; 一个是数据&#xff0c; 一个是指针 next 指向当前结点的下一个结点&…

匿名管道

1.进程通信的目的 (1) 数据传输: 一个进程需要将它的数据传输给另一个进程     (2) 资源共享: 多个进程之间共享同样的资源     (3) 通知事件: 一个进程需要向另一个或一组进程发送消息, 通知它们发生了什么事情 2.管道 管道是一种进程之间通信的一种方式, 我们把从…

Currency Exchange——最短路Bellman-Ford算法

【题目描述】 Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the sam…

C++实现String类

http://blog.csdn.net/randyjiawenjie/article/details/6709539 C实现String类&#xff0c;还没有完成&#xff0c;待继续。 有以下注意的点&#xff1a; &#xff08;1&#xff09;赋值操作符返回的是一个MyString&&#xff0c;而重载的返回的是一个MyString。其中的原因…

POJ 3370 Halloween treats——鸽巢原理+思维

【题目描述】 POJ 3370 Halloween treats Description Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets on that day, no matter how many children call on him, so it may happen that a chi…

将信号量代码生成静态库以及动态库

1.信号量相关代码生成静态库 2.信号量相关代码生成动态库

Wormholes——Bellman-Ford判断负环

【题目描述】 While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of…

C++11 标准新特性:Defaulted 和 Deleted 函数

https://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/index.html Defaulted 函数 背景问题 C 的类有四类特殊成员函数&#xff0c;它们分别是&#xff1a;默认构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。这些类的特殊成员函数负责创建、初始化、…

顺序表实现栈相关操作

1.栈的相关概念 栈是一种特殊的线性表, 其中只允许在固定的一端进行插入和删除元素.进行数据插入和删除的一端叫做栈顶, 另一端成为栈底. 不含任何元素的栈称为空栈, 栈又称为先进先出的线性表. 2. 顺序栈的结构 3. 顺序栈的具体操作 (1). 数据结构 typedef char SeqStackTyp…

MPI Maelstrom——Dijkstra

【题目描述】 BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchical communication subsystem. Valentine McKee’s research advisor, Jack Swigert, has asked her to bench…

双向带环带头结点的链表实现栈

1. 数据结构 利用带头结点带环的结点实现栈的相关操作.因此, 每一个结点包括了一个前驱, 一个后继, 还有一个数据成员 typedef char DLinkStackType;typedef struct DLinkStack {DLinkStackType data;struct DLinkStack* next;struct DLinkStack* prev; }DLinkStack;2. 初始化…

Cow Contest——Floyed+连通性判断

【题目描述】 N (1 ≤ N ≤ 100) cows, conveniently numbered 1…N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors. The contest …

C++11 标准新特性:委派构造函数

https://www.ibm.com/developerworks/cn/rational/1508_chenjing_c11/index.html陈 晶2015 年 8 月 11 日发布WeiboGoogle用电子邮件发送本页面 1本文首先介绍了在委派构造函数提出之前类成员构造所面临的问题&#xff0c;再结合实例介绍了委派构造函数的用法&#xff0c;并说明…

顺序表实现队列

一. 队列相关概念 队列是只允许在一段进行插入元素, 在另一端进行删除元素的线性表,即只允许对队列进行尾插,头删的操作.队列具有先进先出, 后进后出的特性.          1.初始化 void SeqQueInit(SeqQue* q) {if(q NULL){return;//非法输入}q -> head 0;q -> …

Arbitrage——判断正环Bellman-Ford/SPFA

【题目描述】 Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound, 1 British pound buys 10.0 French …