思路分析
暴力算法
第一种最容易想到的就是暴力算法,但是时间复杂度为O(n^2)
private static ListNode findCommon(ListNode la, ListNode lb) {
if (la == null || lb == null) {
return null;
}
ListNode p1 = la;
ListNode p2 = lb;
while (p1.next != null) {
while (p2 != null) {
if (p2 == p1) {
return p2;
}
p2 = p2.next;
}
p2 = lb;
p1 = p1.next;
}
return null;
}
HashSet集合
第二种方法是通过HashSet或者HashMap的方法逐一匹配,两次循环即可,时间复杂度为O(n)
先将一个链表存储到Set中,再通过一次遍历另一条链表,在遍历的过程中进行匹配寻找是否有交点
public static ListNode findFirstCommonNodeBySet(ListNode headA, ListNode headB) {
Set<ListNode> set = new HashSet<>();
while (headA != null) {
set.add(headA);
headA = headA.next;
}
while (headB != null) {
if (set.contains(headB))
return headB;
headB = headB.next;
}
return null;
}
栈
第三种方法是通过栈的方法实现,先把两个链表分别存进两个栈中,利用栈后进先出的特点从后往前遍历,直到无法相等才结束
public static ListNode findFirstCommonNodeByStack(ListNode headA, ListNode headB) {
Stack<ListNode> stackA = new Stack();
Stack<ListNode> stackB = new Stack();
while (headA != null) {
stackA.push(headA);
headA = headA.next;
}
while (headB != null) {
stackB.push(headB);
headB = headB.next;
}
ListNode preNode = null;
while (stackB.size() > 0 && stackA.size() > 0) {
if (stackA.peek() == stackB.peek()) {
preNode = stackA.pop();
stackB.pop();
} else {
break;
}
}
return preNode;
}
拼接字符串
由于两条链表的长度不一样,无法进行逐一比较,但是将他们分别拼接后最后就可以找到相同结点
public static ListNode findFirstCommonNodeByCombine(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null || pHead2 == null) {
return null;
}
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
if (p1 != p2) {
if (p1 == null) {
p1 = pHead2;
}
if (p2 == null) {
p2 = pHead1;
}
}
}
return p1;
}
差和双指针
由于要匹配的链表长度可能不同,所以需要先找出长链表和短链表
让长链表先走他们长度的差值,然后两个指针就可以进行逐一匹配了
public static ListNode findFirstCommonNodeBySub(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null || pHead2 == null) {
return null;
}
ListNode current1 = pHead1;
ListNode current2 = pHead2;
int l1 = 0, l2 = 0;
while (current1 != null) {
current1 = current1.next;
l1++;
}
while (current2 != null) {
current2 = current2.next;
l2++;
}
current1 = pHead1;
current2 = pHead2;
int sub = l1 > l2 ? l1 - l2 : l2 - l1;
if (l1 > l2) {
int a = 0;
while (a < sub) {
current1 = current1.next;
a++;
}
}
if (l1 < l2) {
int a = 0;
while (a < sub) {
current2 = current2.next;
a++;
}
}
while (current2 != current1) {
current2 = current2.next;
current1 = current1.next;
}
return current1;
}