题目描述
输入两个链表,找出它们的第一个公共结点。
做法有两种:
1、利用HashSet,先将第一个链表中所有节点放入,Set集合中,然后遍历第二个链表,找出第一个和Set集合中匹配的节点。时间复杂度为O(n)
2、利用特性,因为两个链表有公共节点,那么从公共节点开始,他们后面的所有节点数目是一致的。所以,让较长链表先走length长度,直到两个链表的剩余节点数目一致,然后两个链表一起走,直到找到所有节点。时间复杂度O(n)
3、让两个链表的节点一起走,当某一个走到链表的尾部时,指向另一个链表的头部继续遍历。这个做法和第二种实质是一样的,如果两个链表长度不同,当两个链表的指针都分别指向了对方的头指针时,情况就和第二种一样了。只是,这种算法,代码更简洁。具体思路,只要自己模拟一下就立刻明白了。
1、第一种解法
import java.util.HashSet;
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
HashSet<ListNode> set = new HashSet<>();
if(pHead1==null || pHead2==null) return null;
ListNode p1 = pHead1,p2 = pHead2;
while(p1!=null){
set.add(p1);
p1 = p1.next;
}
while(p2!=null){
if(set.contains(p2)){
return p2;
}
p2 = p2.next;
}
return null;
}
}
2、第二种解法
public ListNode FindFirstCommonNodeII(ListNode pHead1, ListNode pHead2) {
ListNode current1 = pHead1;// 链表1
ListNode current2 = pHead2;// 链表2
if (pHead1 == null || pHead2 == null)
return null;
int length1 = getLength(current1);
int length2 = getLength(current2);
// 两连表的长度差
// 如果链表1的长度大于链表2的长度
if (length1 >= length2) {
int len = length1 - length2;
// 先遍历链表1,遍历的长度就是两链表的长度差
while (len > 0) {
current1 = current1.next;
len--;
}
}
// 如果链表2的长度大于链表1的长度
else if (length1 < length2) {
int len = length2 - length1;
// 先遍历链表1,遍历的长度就是两链表的长度差
while (len > 0) {
current2 = current2.next;
len--;
}
}
//开始齐头并进,直到找到第一个公共结点
while(current1!=current2){
current1=current1.next;
current2=current2.next;
}
return current1;
}
// 求指定链表的长度
public static int getLength(ListNode pHead) {
int length = 0;
ListNode current = pHead;
while (current != null) {
length++;
current = current.next;
}
return length;
}
3、最简单
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;
}
}