单链表面试题总结

假设单链表节点为

struct node{

       int data;

       struct node* next;

}


链表名为list,已知头结点为head

一.    单链表反转

1.     pre-cur-next法,最常用的方法

2.     前插法,实质就是在原链表的基础上新建一个链表,每次新节点都插到head后面,而不是最后面

structnode* p   =   head;
struct node* q   =   NULL;
head =   NULL;

while(p)
{
      q   =   p-> next;
      p-> next   =   head;
      head =   p;
      p   =   q;
}


二.    单链表逆序输出

有很多方法。

1.     ,每读一个,将节点地址压栈,读完后,弹栈读出

时间复杂度, 空间复杂度

 

2.     递归,先递归输出当前节点下一结点为头结点的单链表,然后输出当前节点

时间复杂度, 空间复杂度,适合比较短的单链表,不然递归深度太深容易爆栈

 

3.     先逆序,先求单链表的逆序,然后再按照新的逆序链表顺序输出。

其中逆序有两种方法,pre-cur-next法和前插法。

时间复杂度, 空间复杂度,要遍历两遍链表,而且还破坏了其结构,若要保持结构就要再反转一次,共3次遍历

 

三.    判断单链表里面是否有环

算法的思想是设定两个指针p, q,其中p每次向前移动一步,q每次向前移动两步。那么如果单链表存在环,则p和q相遇;否则q将首先遇到null

 

原理:

假设p走了k步就和q相遇了

则 ,即 ,k=n,即p必在最后一个节点与q相遇。若无环,则q走了n步,p走了n/2步,q就遇到了遇到null

这里一个简单的理解是,p和q同时在操场跑步,其中q的速度是p的两倍,当他们两个同时出发时,p跑一圈到达起点,而q此时也刚好跑完两圈到达起点。

 

如果p,q不是同一起点出发,例如p到达 时,q到达

那么如果有环,则,即k=n-m,当,k=n-m时,p,q相遇

 

四.    找链表中第一个在环里的节点

 单链表面试题总结_第1张图片

如上图,p,q同时从1出发,当p到达i之后,q在2i,把1,2,…i-1删除,剩下环,那就想当与p,q不是同一起点出发,有上面“三”中最后的结论可知,p,q必将交与n-i,(n是环的节点数),在换上n-i到0是i步,从红色起点0开始到i处也是i步,所以在找到交点A之后,让p从链表起点出发,q从A出发,当p,q相等的时候,那个节点就是环的第一个节点

总结:

1.      p,q 同时从起点出发,p每次走一步,q每次走两步

2.      如果q走到了null,终止,无交点,否则一直到p,q相遇

3.      p,q相遇时,p回到起点,q不动,都每次走一步,直到p,q相遇,相遇的点就是交点

五.    判断两个单链表是否交?第一个交点在哪里?

1.     因为如果相较,则最后一个节点肯定是相同的,所以,只有两个链表都找到最后一个节点,看是否相同

2.     第一个交点问题有两种解法

六.    一是转化为上面的找环的第一个节点,如下图,将一个链表的尾部链接到另一个的头部,就形成了上面的“找链表中第一个在环里的节点”问题了。

     二是直接先计算两个链表的长度,len1,和len2,假设len1>len2,p从L1的len1-len2那个节点开始,q从L2的其实节点开始,两个指针依次后移,第一次两个指针相等的地方就是交点

 

 单链表面试题总结_第2张图片


你可能感兴趣的:(单链表面试题总结)