题目描述
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
解法
这题首先需要理解两个链表的公共节点的意思,如果两个链表有公共节点,说明两个链表都指向同一个节点,因为引用数据类型在堆中存储的是地址,那么相遇后就合并成一条链了,如下图所示
计算长度法
一个最直观的解法是分别计算链表A和B的长度,然后将长的链表和短的链表对齐,齐头并进,找到地址相同的公共节点
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
// 计算两个链表的长度
int len1 = 0, len2 = 0;
ListNode tmp1 = pHead1, tmp2 = pHead2;
while (tmp1 != null) {
tmp1 = tmp1.next;
len1++;
}
while (tmp2 != null) {
tmp2 = tmp2.next;
len2++;
}
// 对齐,让长的链表头先走一段距离,和短的链表对齐
if (len1 > len2)
for (int i = 0; i < (len1 - len2); i++)
pHead1 = pHead1.next;
if (len2 > len1)
for (int i = 0; i < (len2 - len1); i++)
pHead2 = pHead2.next;
// 齐头并进,找出公共节点
while (pHead1 != null && pHead2 != null) {
if (pHead1 == pHead2)
return pHead1;
pHead1 = pHead1.next;
pHead2 = pHead2.next;
}
return null;
}
优化解法
这个解法相当于把两个链表连在一起了,例如对于两个链表
A: 0-1-2-3-4-5-null
B: a-b-4-5-null
下面的代码相当于把两个链表拼在一起,即0-1-2-3-4-5-null--a-b-4-5-null
和a-b-4-5-null--0-1-2-3-4-5-null
,拼接后两个链表长度一样,一起齐头并进找到公共节点
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode tmp1 = pHead1, tmp2 = pHead2;
while (tmp1 != tmp2) {
if (tmp1 != null)
tmp1 = tmp1.next;
if (tmp2 != null)
tmp2 = tmp2.next;
if (tmp1 != tmp2) {
if (tmp1 == null)
tmp1 = pHead2;
if (tmp2 == null)
tmp2 = pHead1;
}
}
return pHead1;
}