整体思路:
利用两个链表公共部分一模一样,对齐两个链表来解题。
题解一 差值法
如图,计算两个链表各自的长度,计算差值,让较长的链表指针先走差值下,这样两个链表就对齐了,接下来同步地移动指针,逐项对比,第一个相同的节点就是要找到的第一个公共节点。
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
int distance = size(pHead2) - size(pHead1);
ListNode temp_long = null;
ListNode temp_short = null;
//确定谁是较长,谁是较短,并确定差值
if(distance < 0) {
distance = -distance;
temp_short = pHead2;
temp_long = pHead1;
} else {
temp_short = pHead1;
temp_long = pHead2;
}
//较长的链表指针先走distance步
for(int i = 0; i < distance; i++) {
temp_long = temp_long.next;
}
//开始逐项对比
while(temp_short != null) {
if(temp_short == temp_long) {
return temp_short;
}
temp_short = temp_short.next;
temp_long = temp_long.next;
}
return null;
}
public int size(ListNode head) {
ListNode temp = head;
int count = 0;
while(temp != null) {
count++;
temp = temp.next;
}
return count;
}
}
题解二 等值法
把两个链表拼接起来,也能实现两个链表一样长的效果。
记:a = list1非公共部位长度,b = list2非公共部位长度,c = 公共部位长度。
如上图,list1遍历到最后,让list1的指针指向pHead2
,接着往后遍历list2。list1的指针走a + c + b
步刚好到达第一个公共节点。
(注:图中虚线表示这个箭头并不是真的指针,即list1和list2并非真的拼接成一个链表,虚线箭头只是表示遍历的节点顺序。)
如上图,list2遍历到最后,让list2的指针指向pHead1
,接着往后遍历list1。list2的指针走b + c + a
步刚好到达第一个公共节点。
综上,两个链表的指针分别按照上述顺序去遍历。因为两个指针最后走相同的步数,因此遍历过程中可以逐个节点对比,第一次对比相同的节点,就是要找的第一个公共节点。
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode temp1 = pHead1, temp2 = pHead2;
while(temp1 != temp2) {
if(temp1 != null) {
temp1 = temp1.next;
} else {
temp1 = pHead2;
}
if(temp2 != null) {
temp2 = temp2.next;
} else {
temp2 = pHead1;
}
}
return temp2;
}
}