LeetCode算法题160相交链表三种解法,java实现

题目描述如下:

编写一个程序,找到两个单链表相交的起始节点。

如下面的两个链表:

LeetCode算法题160相交链表三种解法,java实现_第1张图片

在节点 c1 开始相交。

示例 1:
LeetCode算法题160相交链表三种解法,java实现_第2张图片

输入: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 个节点。

示例 2:
LeetCode算法题160相交链表三种解法,java实现_第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:

LeetCode算法题160相交链表三种解法,java实现_第4张图片

输入: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;
    }//双指针巧解法

好了所有的解法都解释完毕了,这道题还是很有意思的。

你可能感兴趣的:(java)