算法热门:环形链表的又一解法(LeetCode 142)
Posted 白龙码~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法热门:环形链表的又一解法(LeetCode 142)相关的知识,希望对你有一定的参考价值。
Part I、温故而知新
对环形链表和链表相交问题不清楚的同学可以先看看下面这两篇文章哦——
《环形链表问题》
《相交链表问题》
Part II、question
在我们清楚了链表相交之后,这个问题就有了一个新的突破点!
且看下图:
我们知道,想求得环的入口,需要做的第一步就是先确认链表是否带环。如果带环,我们再让一个指针从头结点开始走,另一个指针从相遇点开始走,然后它们奇迹般的相遇在入口处。
这种方式固然非常好,但是非常抽象、难以证明。
那么今天我们采取一种新鲜的方法,让这道题变个方向。
Part III、交融
看着下面这幅图,
我们可以发现:如果把原链表的头看做链表A的头指针,快慢指针的相遇点看成链表B的头指针,那么环的入口是不是就成了链表A和链表B的交点?
不过,需要注意的是,由于找交点的函数中有从头到尾遍历链表求链表长度的过程,所以需要在快慢指针的相遇点处断开,也就是说:
思路非常简单,代码实现一波:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
//方法二、求出两链表的长度差x,让长的链表先走x,然后两链表再一起走,找出相同的节点
struct ListNode* cur1 = headA, *cur2 = headB;
int len1 = 0, len2 = 0;
while(cur1)
{
cur1 = cur1->next;
len1++;
}//求链表A的长度
while(cur2)
{
cur2 = cur2->next;
len2++;
}//求链表B的长度
struct ListNode* longList = headA, *shortList = headB;
if(len2 > len1)
{
longList = headB;
shortList = headA;
}//找出长的那个链表
int n = abs(len1-len2);//求出长度差
while(n--)
{
longList = longList->next;//让长的链表先走n个结点
}
while(longList && shortList)//遍历,找到相同的节点
{
if(longList == shortList)
return longList;
longList = longList->next;
shortList = shortList->next;
}
return NULL;
}
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode* slow = head, *fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)//slow和fast相遇,链表带环
{
struct ListNode* pA = head, *pB = slow->next;//找到A、B两个链表的头
slow->next = NULL;
struct ListNode* ret = getIntersectionNode(pA, pB);//找A、B两个链表的交点
return ret;
}
}
return NULL;
}
Part IV、总结
可以看到,这种将环形链表问题转成相交问题的解法非常灵活,综合性也更高,对于我们的技术要求也更高,但是优点就是:相对于更具技巧性的双指针解法,该解法更加亲民。
学习更多的解法,也是为了积累更多的经验,拓展自己的知识面!
欢迎关注博主,定期分享各种题解!==
以上是关于算法热门:环形链表的又一解法(LeetCode 142)的主要内容,如果未能解决你的问题,请参考以下文章