【链表经典面试题保姆级题解】什么?这八个最基本的链表面试题你还没有掌握?最短的时间内教会你!

大家好啊O(∩_∩)O~~,可能大家是被标题吸引进来的吧,在这里先道一声歉,博主会尽力不做标题党,达成点进文章的大家的期待的!如果真的让您有收获的话,还请点个三连支持一下呗~今后会持续更新优质内容,为您答疑解惑的~~~~

话不多说,马上开始!另外,别忘记看结尾处的知识总结喔(⊙o⊙)~~

———————————————————————————————————————————

目录

1. 移除链表元素

2.反转链表

 3.链表的中间结点

4.链表中倒数第k个结点

5.合并两个有序链表

6.链表分割

7.链表的回文结构

8.相交链表

知识总结(重点):


1. 移除链表元素

题目

分析:

首先要仔细分析题目所给出的几个示例

可以分为大致两种情况:

1.要删除的节点在头部

2.要删除的节点不在头部

那么该如何进行删除操作呢?

如下图:

 这是一个最常规的状况:

要删除的节点不在头部,此时cur 指向的结构体内存储的数值就是要删除的值。我们需要让prev->next==cur->next  ,free掉cur  ,然后让cur=prev->next。

当然这里可以采用的方式有很多,比如可以定义一个临时变量记住要删除的结点的位置,之后让cur=cur->next  ,prev->next=cur  ,再free。

如果要删除的节点在头部呢?

很简单,只需要让head=head->next  ,然后free即可。

如果不需要进行删除操作的话,只需要让prev和cur迭代下去就可以:prev=cur,cur=cur->next。

将以上情况包装进一个循环即可,循环的条件是cur不为NULL。

关于链表为空这种特殊情况,循环不会进入,会直接返回head,也就是NULL,所以不必另外考虑了

代码实现:

 ——————————————————————————————————————————

2.反转链表

题目:

分析:

第一种方法:

使用头插。只需要一个新的头,然后遍历原链表,依次头插即可。不过在头插的时候,需要有一个指针next来记录cur的下一个位置,协助链表的遍历。还要注意一下特殊情况:链表为空。

代码:

不过在这里链表为空的情况也可以被解决:如果链表为空,循环不会进入,会直接返回newhead,此时newhead==NULL,满足题意。

分析:

第二种方法:

 不使用新的头,而是直接在原地反转链表,此时需要三个指针,一个是需要改变指向的指针n2,一个是要被指向的节点的指针n1,另一个指针n3是要记住下一个节点,防止在反转的时候与链表的后半段丢失联系。

当n2为空时,结束循环,返回n1。

代码:

———————————————————————————————————————————

 3.链表的中间结点

题目:

分析:

暴力遍历链表的节点数量可以解决,但是效率很低,所以在此不介绍

我们要用快慢指针的方法来解决:

所谓快慢指针,顾名思义就是两个指针,一个指针走的快,一个指针走的慢。

针对此题,我们要让快指针fast一次走两步,慢指针slow一次走一步,这样在快指针走到链表末尾的时候,慢指针所指向的就是链表的中间结点了。

但是还是要分情况讨论一下:

1.链表节点的数量为偶数

 可以看到当fast指向NULL的时候,slow正好指向了第二个中间节点。

2.链表节点数量为奇数

 可以看到,当fast->next指向NULL的时候,slow指向中间节点,并且此时必须退出循环,因为如果继续迭代fast就会对空指针进行解引用,会导致程序崩溃。

3.链表为空

此时不会进入循环,可以被归到常规情况里面

———————————————————————————————————————————

对以上情况进行了讨论后,while循环的条件就应该是fast!=NULL&&fast->next!=NULL。出循环后返回slow就好。

 ——————————————————————————————————————————

4.链表中倒数第k个结点

题目:

 分析:

这题也可以暴力解决,但是太挫了。

我们采用双指针法:让快指针先走k步,慢指针=head,当快指针为空时,慢指针就指向倒数第k个结点了。

不过别忘了还有特殊情况:

1.如果链表本身为空,直接返回NULL

2.如果k的值没有实际意义,比方说:k的值大于链表的长度,此时是不存在倒数第k个节点的。在让快指针走k步的时候,就会对空指针解引用,我们要在这之前返回NULL。

代码:

———————————————————————————————————————————

5.合并两个有序链表

题目:

分析:

大体思路:我们需要重新创建一个头指针,然后遍历两个链表,比较数值大小后,依次将两个链表的每个节点尾插到新的链表中去,返回新的链表的头指针即可。

细致分析的话要分为两种情况:

第一种:

两个链表都不是空链表,在遍历并插入的时候,必然会有一个链表先被遍历完,此时需要对两个链表是否为空进行判断,如果某个链表为空,那么就将另一个链表剩下的节点尾插到新链表。

第二种:

如果有任何一个链表是空的,那么直接返回另一个链表的头指针即可。

———————————————————————————————————————————

代码:

不带哨兵位的头结点:


 

 带哨兵位的头结点:

————————————————————————————

6.链表分割

题目:

 分析:

其实我觉得题目的描述是有问题的,不应该是“不能改变原来的数据顺序”,而应该是“不能改变原来的相对数据顺序”,第一次做这个题的时候我就没读明白,出题者语文不好啊O(∩_∩)O~。

哈哈哈哈不闹了。

此题如果只创建一个新的头指针的话,是不好办的。

我们要创建两个头指针head1,head2,尾指针tail1,tail2 : head1用于尾插小于x的值,head2用于尾插大于等于x的值。

最后再将两个链表链接并返回即可。

特殊情况:

如果链表为空,直接返回空即可

另外,还有许多的情况,比如:如果原链表中没有小于x的值的话,那么head1就是空的,进行链接操作(tail1->next=head2)的时候,就会对空指针(tail1==NULL)进行解引用导致崩溃。

所以为了免除这些麻烦,不如直接采用带哨兵位头结点的结构。

代码(有缺陷):

但是运行结果却是:

 

 这简直离谱啊,我们的程序竟然使用了超过限制的内存,一般情况下,所给的内存是完全够用的啊

 这个是另一个题占用的内存,只有460KB,这只能说明,我们的代码出错了,很有可能出现了死循环的情况。

这个时候,需要对未通过的例子进行细致的分析,从而找出错误,一定要细致哦!

比如说这个例子:

 我们以为是这样:

但实际上是这样:

 

 这样就造成了死循环,那么如何解决呢?

我们只需要让大于等于x的链表的最后一个节点指向NULL就可以了,于是:

———————————————————————————————————————————代码:

———————————————————————————————————————————

7.链表的回文结构

题目:

 分析:

找到链表的中间节点,并将此中间节点当做头指针来反转之后的节点,如下图所示:

偶数个节点:

 奇数个节点:

 可以看到都是可以的。

反转之后,只要依次对比两个链表的数值即可。

如果链表为空或者只有一个节点都直接返回空即可。

代码:

 ——————————————————————————————————————————

8.相交链表

题目:

 分析:

将两个链表遍历到尾节点,并在此过程中计算两个链表的节点数量n1,n2,如果尾节点指针相同,就说明两个链表相交,不相同则直接返回NULL。

如果两个链表相交的话,让比较长的链表先走|n2-n1|步,之后同步走,直到二者某个节点的地址相同,返回即可。

代码:

 ——————————————————————————————————————————

知识总结(重点):

1.做题的时候,经常会创建新的链表,只要是为了效率,不要吝惜空间。

2.经常会使用多指针法,快慢指针法。

3.有的时候使用带哨兵位的头结点的结构,可以大大简化代码

4.画图一定要足够细致。

5.如果发生了空间不足的错误,很有可能是某个地方发生了死循环。

6.要预防对空指针的解引用操作,多考虑特殊的情况

7.如果发生了错误,不要慌,对着没通过的例子进行逐步细致的分析即可

8.

 可以采用这种妙法,让shortlist必然是短的链表,longlist必然是长的链表。

谢谢大家,都看到这里了,如果有收获的话,给个三连吧!

 

 

 

  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值