最近这几篇内容都有关链表,接下来几篇内容会分享一些链表的OJ题,希望对你有所帮助。
今天要分享的内容是力扣160. 相交链表:160. 相交链表 - 力扣(LeetCode)
目录
题目:
题解
题目:
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
listA - 第一个链表
listB - 第二个链表
skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。
题解
首先要说的是链表的相交并不能像一个大叉一样
因为如上这样的小圈中都代表着一个节点,而每个节点中只有一个结构体变量next,所以无法分开指向两个节点,所以真正的链表相交应该是如下图
接下来探究一下链表相交的方法
1.判断尾结点是否相等,为结点相等两个链表相交;
2.找交点:分别求出链表A和链表B的长度,先让长的链表走出两个链表差距的长度,再同时走,当两个链表第一次相等时就是焦点;
以下是本题代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode *tailA=headA;
struct ListNode *tailB=headB;
int lenA=1;
int lenB=1;
//判断两个链表是否有交点
while(tailA->next)
{
tailA=tailA->next;
++lenA;
}
while(tailB->next)
{
tailB=tailB->next;
++lenB;
}
if(tailA!=tailB)//不相交返回空
{
return NULL;
}
//长链表先走差距步
int gap=abs(lenA-lenB);
struct ListNode *longList=headA;
struct ListNode *shortList=headB;
if(lenA<lenB)
{
longList=headB;
shortList=headA;
}//判断A和B的长短
while(gap--)
{
longList=longList->next;
}
while(longList!=shortList)
{
longList=longList->next;
shortList=shortList->next;
}
return longList;
}
对照着代码我们一步一步来说;
以上代码的注释也非常清楚;
1.首先链表相交就要判断他们是否有交点,如果没有交点就返回NULL(空)。因为链表停止的标志是最后一个结点是否指向空,所以可以利用tailA来操作结构体指针next来判断,并且使用len来标志两个链表的长度;
2.如上解题思路,需要判断两个链表哪个长哪个短,长的先走差距步数,再一起走,再判断交点。这时就需要使用绝对值函数abs,他是用来计算绝对值的函数,这样就可以计算两个链表的差距步数;
3.最后让结点向后迭代并判断,两个链表有交点就说明指向的结点是一样的,所以可以将两个链表进行对比,用“当两个结点不相等时就像后迭代”作为判断条件,在末尾返回即可 (两个结点同时向后迭代,所以返回shortList和longlist都是正确的);