题目内容
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
题目分析
这道题的难度在于理解清楚题意,链表的结点时这样定义的:
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
所以,作为公共结点,不应该只是value值相等,next指针指向的结点也应该相同,next指向的结点相同,也就是公共结点以后的结点都一样。用图来表示可能就是一个“Y”型的链表。
解题
解法一
双指针法。思路来源于牛客网的lizo大佬,假设有两个链表{A, B, C, D, X, Y, Z},长度为7;{E, F, X, Y, Z},长度为5,定义两个指针分别指向两个链表的头结点,链表1比链表2长两个结点,因为之前分析说了,公共结点以后的结点全部相同,那么链表1的指针先走两步,然后两个指针一起走,如果有一样的指针即为第一个公共结点。
代码
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(pHead1 == NULL || pHead2 == NULL)
return NULL;
int length1 = 0;
int length2 = 0;
ListNode* currpNode1 = pHead1;
ListNode* currpNode2 = pHead2;
while(currpNode1 != NULL){
length1++;
currpNode1 = currpNode1->next;
}
while(currpNode2 != NULL){
length2++;
currpNode2 = currpNode2->next;
}
currpNode1 = pHead1;
currpNode2 = pHead2;
if(length1 > length2){
int step = length1 - length2;
while(step){
currpNode1 = currpNode1->next;
step--;
}
}else{
int step = length2 - length1;
while(step){
currpNode2 = currpNode2->next;
step--;
}
}
while(currpNode1 != NULL){
if(currpNode1 == currpNode2)
break;
currpNode1 = currpNode1->next;
currpNode2 = currpNode2->next;
}
return currpNode1;
}
};
解法二
思路来源于一叶浮尘大佬,还是解法一中的例子,我们把它们接到一起,那么就变成了:
- 链表1:{A, B, C, D, X, Y, Z, null, E, F, X, Y, Z, null}
- 链表2:{E, F, X, Y, Z, null, A, B, C, D, X, Y, Z, null}
可以很直观的看到同时遍历,最后可以找到第一个公共结点X。
代码
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(pHead1 == NULL || pHead2 == NULL)
return NULL;
ListNode* currpNode1 = pHead1;
ListNode* currpNode2 = pHead2;
while(currpNode1 != NULL || currpNode2 != NULL){
if(currpNode1 != currpNode2){
if(currpNode1 == NULL)
currpNode1 = pHead2;
else
currpNode1 = currpNode1->next;
if(currpNode2 == NULL)
currpNode2 = pHead1;
else
currpNode2 = currpNode2->next;
}else{
break;
}
}
return currpNode1;
}
};
以上思路为个人想法和网络各位大佬的题解的结合,欢迎讨论与指正。