题目描述如下:
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在节点 c1 开始相交。
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例 3:
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
官方的题解提供了三种思路。1、暴力法,2、哈希表法,3、双指针法在这里会一种一种的讲解。
首先是暴力法,最容易想到的,在从A链表的头开始和链表B的每一个节点的地址进行比较,如果有两个地址相同的说明两链表有节点是相同的(即相交)照着这个思路就很容易写代码了
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null){
return null;
}
ListNode flagA=headA;
do {
ListNode flagB=headB;
do {
if(flagA==flagB) {
return flagA;
}else {
flagB=flagB.next;
}
}while(flagB!=null);
flagA=flagA.next;
}while(flagA!=null);
return null;
}//暴力法
复杂度分析
时间复杂度 :
O(mn)。
空间复杂度 :
O(1)。
第二种使用空间换时间的方法,利用哈希表储存A链表的每一个节点的地址,在利用哈希表在查找上的优势来降低时间复杂度,A链表所有的节点地址都在哈希表中之后和链表B中的节点地址匹配即可,使用函数containsKey()。代码如下:
public ListNode getIntersectionNode1(ListNode headA, ListNode headB) {
if(headA==null||headB==null) {
return null;
}
HashMap nodeOfHeadA=new HashMap();
ListNode pA=headA;
while(pA!=null) {
if(!nodeOfHeadA.containsKey(pA)) {
nodeOfHeadA.put(pA,pA.val);
}
pA=pA.next;
}
ListNode pB=headB;
while(pB!=null) {
if(nodeOfHeadA.containsKey(pB)) {
return pB;
}
pB=pB.next;
}
return null;
}//哈希表法
最后一种方法巧妙的构造出一个循环链表,将问题大大简化,以示例2简单的说明一下先创建两个指针(姑且叫指针吧)pA,pB,分别指向headA,headB,但pA遍历到1的时候,pB便利到最后一个节点4,此时将pB=headA;下一步遍历pB是A的节点0,pA到2;再下一步pB到9,pA到4,再将pA=headB;再下一步pB到1,pA到3;下一步两指针汇聚在一点(即相交)。图解
代码如下:
public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
if(headA==null||headB==null) {
return null;
}
ListNode pA=headA,pB=headB;
while(pA!=pB) {
if(pA==null) {
pA=headB;
}else {
pA=pA.next;
}
if(pB==null) {
pB=headA;
}else {
pB=pB.next;
}
}
return pA;
}//双指针巧解法
好了所有的解法都解释完毕了,这道题还是很有意思的。