输入两个链表,找出它们的第一个公共节点。
如下面的两个链表:
注意:
- 如果两个链表没有交点,返回 null.
- 在返回结果后,两个链表仍须保持原有的结构。
- 可假定整个链表结构中没有循环。
- 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
解题思路:
可以先计算两个链表的长度,长度差为n,首先,比较长的链表header先往后移动n步,然后两个链表一起往后移动,如果一样,则为公共节点。
package com.alibaba.study.offer;
/**
* @Auther: wjj
* @Date: 2020/12/16 18:43
* @Description:
*/
public class Offer52 {
public static void main(String[] args) {
ListNode node1 = new ListNode(4);
ListNode node2 = new ListNode(1);
ListNode node3 = new ListNode(8);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(5);
ListNode node7 = new ListNode(0);
ListNode headA = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node6.next = node7;
node7.next = node2;
ListNode headB = node6;
ListNode intersectionNode = getIntersectionNode(headA, headB);
System.out.printf("end...");
}
public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenA = 0;
int lenB = 0;
ListNode tempA = headA;
while (tempA != null){
lenA++;
tempA = tempA.next;
}
ListNode tempB = headB;
while (tempB != null){
lenB++;
tempB = tempB.next;
}
int substract = 0;
if(lenA > lenB){
substract = lenA - lenB;
while (substract > 0){
headA = headA.next;
substract--;
}
} else {
substract = lenB - lenA;
while (substract > 0){
headB = headB.next;
substract--;
}
}
ListNode start = null;
while (headA != null){
if(headA.val == headB.val && start == null){
start = headA;
} else if(headA.val != headB.val){
start = null;
}
headA = headA.next;
headB = headB.next;
}
return start == null ? null : start.next;
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
解法二:
我们使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结点遍历,当 node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。
这样,当它们相遇时,所指向的结点就是第一个公共结点。
public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
ListNode a = headA;
ListNode b = headB;
while (headA != headB) {
headA = headA != null ? headA.next : b;
headB = headB != null ? headB.next : a;
}
return headA;
}