链表的两大劣势就是无法快速访问某个元素和涉及链表的长度问题,但是有这么几个题就是专门针对这方面出的,例如:
- 法一:
法一思路:让两个链表pA和pB分别遍历往后走,谁先到了尾谁就赋值为另一条链表的头,再继续一起走,当他们相交的时候就是目标结点
刚开始看这段话大家应该看不明白,可以这么理解:在相交之前,它们走过的路程其实是相同的,因为两个指针速度相同,想要相遇那么走过的路程肯定会相等,否则怎么可能会撞到一起?
**如下图,P2先碰到了NULL,那么赋值为HeadA,走一遍HeadA的路程,当P1也到了NULL时,就赋值为HeadB,走HeadB的路程
到Head的步骤是赋值,不需要走。
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
struct ListNode* pA = headA;
struct ListNode* pB = headB;
while (pA != pB)
{
pA = pA == NULL ? pA = headB : pA->next;
pB = pB == NULL ? pB = headA : pB->next;
}
return pA;
}
- 法二:
法二思路:如果这两个单链表pA,pB相交,那它们一定会有相同的尾结点,而且它们的长度相差多少未知。那么可以先让pA,pB分别遍历一遍链表,记录其长度,然后得到长度的差值gap,再让长的链表(假设为pA)先走gap步,那么它们会处于同一出发点,当pA和pB相等的时候就是那个目标结点
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
//遍历A计数
struct ListNode* tmp = headA;
int count = 1;
while(tmp)
{
tmp = tmp->next;
count++;
}
//遍历B计数
struct ListNode* scendtmp = headB;
int scendcount = 1;
while(scendtmp)
{
scendtmp = scendtmp->next;
scendcount++;
}
//没有公共尾结点说明不相交
if(scendtmp != tmp)
{
return NULL;
}
//假设其中一个为长,让它先走gap步
struct ListNode* longlist = headA;
struct ListNode* shortlist = headB;
if(count < scendcount)
{
longlist = headB;
shortlist = headA;
}
int gap = abs(count - scendcount);
while(gap--)
{
longlist = longlist->next;
}
//若相等就说明找到了目标点
while(longlist != shortlist)
{
longlist = longlist->next;
shortlist = shortlist->next;
}
return shortlist;
}