题目描述
输入两个链表,找出它们的第一个公共结点。
由于是单链表,所以可以发现从第一个公共节点开始,后面的结点都是相同的,一种思路是从两个链表的尾部开始遍历,直到发现最后一个相同的结点为止,那么这最后一个相同的结点是单链表的角度看就是两个链表的第一个公共节点了。还有一种思路是不需要从尾部开始遍历,毕竟从尾部遍历单链表的话还得使用反转链表的方法进行操作,首先计算出两个链表的长度,让更长的那个单链表先移动两个链表长度差值个位置,然后两个链表同时移动,从更短的那个链表的第一个位置开始遍历,两个链表都往后移动,当发现第一个相同的结点的值的时候,那么该节点就是第一个公共节点了。基于这种思路可以实现如下的代码(已被牛客AC):
package com.rhwayfun.offer;
public class FindFirstCommonListNode {
static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
// 得到两个链表的长度
int pListLengthOf1 = 0;
int pListLengthOf2 = 0;
ListNode temp = pHead1;
while (temp != null) {
pListLengthOf1++;
temp = temp.next;
}
temp = pHead2;
while (temp != null) {
pListLengthOf2++;
temp = temp.next;
}
// 计算两个链表相差的结点个数
int pListNodeDif = pListLengthOf1 - pListLengthOf2;
ListNode pListNodeLong = pHead1;
ListNode pListNodeShort = pHead2;
if (pListNodeDif < 0) {
pListNodeLong = pHead2;
pListNodeShort = pHead1;
pListNodeDif = pListLengthOf2 - pListLengthOf1;
}
// 让较长的那个链表先走几步
for (int i = 0; i < pListNodeDif; i++)
pListNodeLong = pListNodeLong.next;
// 开始寻找
while (pListNodeLong != null && pListNodeShort != null
&& pListNodeLong.val != pListNodeShort.val) {
pListNodeLong = pListNodeLong.next;
pListNodeShort = pListNodeShort.next;
}
//得到两个链表的第一个公共结点
ListNode pFirstCommonListNode = pListNodeLong;
return pFirstCommonListNode;
}
public static void main(String[] args) {
ListNode pHead1 = new ListNode(1);
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(3);
ListNode node3 = new ListNode(6);
ListNode node4 = new ListNode(7);
pHead1.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
ListNode pHead2 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(6);
ListNode node7 = new ListNode(7);
pHead2.next = node5;
node5.next = node6;
node6.next = node7;
ListNode node = new FindFirstCommonListNode().FindFirstCommonNode(pHead1, pHead2);
System.out.println(node.val);
}
}