1.本题知识点
链表,规律
2. 题目描述
输入两个链表,找出它们的第一个公共结点。
3. 思路
1.暴力求解:遍历一个链表的每一个节点分别与另一个链表的每一个节点就行比较,时间复杂度O(mn)。
2.空间换时间(利用栈):时间复杂度为O(m+n),但需要额外的空间 – 栈。
3.巧妙利用规律,时间复杂度为O(m+n),不需要额外的空间。我们来详细介绍这种方式。思路如下:
①求出两个链表的长度差diff;
②先让长链表走diff步,然后2个链表再同时走,直到相遇,此时相遇点即为第一个公共节点。

Java版本:
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) return null;
int len1 = getLen(pHead1);
int len2 = getLen(pHead2);
int diff = len1 - len2;
ListNode nodeLong = pHead1;
ListNode nodeShort = pHead2;
if(len2 > len1){
nodeLong = pHead2;
nodeShort = pHead1;
diff = len2 - len1;
}
for(int i = 0; i < diff; i++){
nodeLong = nodeLong.next;
}
while(nodeLong.next != null && nodeShort.next != null
&& nodeLong != nodeShort)
{
nodeLong = nodeLong.next;
nodeShort = nodeShort.next;
}
if(nodeLong != nodeShort){
return null;
}
return nodeLong;
}
public int getLen(ListNode listNode){
if(listNode == null) return 0;
int len = 1;
while(listNode.next != null){
listNode = listNode.next;
len++;
}
return len;
}
}
还有一种更简单的做法。
思路:直接比较两个链表节点,长度相同时,依次遍历就ok。长度不同时,通过一个交换赋值head的操作,使得两个指针处于链表相同的起跑点,继续循环就是相同长度的情况。

这种方式理解稍微麻烦点,注释已经写的很清楚,代码如下:
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while(p1 != p2){
p1 = p1==null ? pHead2 : p1.next;
p2 = p2==null ? pHead1 : p2.next;
}
return p1;
}
}