快慢指针
貌似是哪个大厂的面试题吧,让你找到一个链表的中间节点,
第一反应遍历数个数,然后跑到中间那个就行了呗。
貌似标准答案也差不多这样,但是有一个dl就不一样,他的思路是这样的:
两个指针,一个慢,一次走一格;一个快,一次走两格。
当快指针到最后,慢指针就到了中点位置了。
例一,求链表倒数第k个结点的元素
利用上面的思想,快慢指针,不过这次是有一个指针先走k’格,然后两个一起前进,当先行的指针到最后,另一个指针的位置就是倒数第k个。
例二,存储两个后缀相同的英文单词
说有两个英文单词,每一个字母都是由链表保存,那么后缀的链表就是相同的,如果能把他们合并,就可以省一部分空间,所以需要找到相同后缀的第一个字母。
方法
首先需要两个单词尾部对齐,计算两个单词的长度,让长的先走,等到对齐了之后两个指针同时后移,找到第一个相同的元素,记录下来然后往后走,直到结束,如果相同就返回,如果有不同的就清除记录,最后的记录就是后缀的起点。(同样如果没有记录就是没有相同后缀)
例三,判断两个链表是否相交
因为链表只有一个指针,所以交叉只可能是两个结点后继相同,不可能是一个结点有两个后继。
地址是每一个链表最好的“元素”,都不带重复的,所以只要对齐了之后看有没有相同的地址就行了。
至于其他的方法也有很多,这个不唯一。
例四,判断链表是否有环
这个比较有趣,如果是单纯判断的话,可以考虑跑步。
如果有环,那必然不论两个人谁快谁慢,必然相遇,但如果没有,那么快的先到NULL,也就是走完。
快慢指针,开始表演。
int judge(struct link* head)
{
struct link* fast=head->next,*slow=head->next;
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)//相遇,有环
return 1;
}//while结束
return 0;
}
但如果还要判断环的入口,这个会比较烦,这其实是一个数学问题(就nm离谱)
现在有三个点,起始点、入口点、指针交点,设起始点和入口点的距离是x,入口和交点的距离是y,快指针走了n圈,一圈r个点。这里一定要明白一个事情,慢指针走一圈,快指针能走两圈多x,所以相遇慢指针必然还没到一圈。
此时慢指针走的距离是x+y,则2(x+y)=nr+(x+y) 则x=nr-y。
来了来了,取一个指针在起始点,另一个指针在交点,在起点的指针走了x之后到达入口点,另一个走了nr-y,算上之前的y,刚好也到达入口点。、
一个比较有趣的,emmm 数学题?