LeetCode160.相交链表

 题目来源:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/description/

题目描述:

解法一:

 先统计两根链表的长度,分别为lenA,lenB。然后两根链表都从头开始遍历,并且让长的链表先跑k步(k为两根链表长度之差)。

然后再同时向后跑,直到跑到相同结点为止。

代码如下:

public class Solution {
	public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
		if (headA == null || headB == null)
			return null;
		ListNode ha = headA, hb = headB;
		int lenA = 1, lenB = 1;
		while (ha.next != null) {
			ha = ha.next;
			lenA++;
		}
		while (hb.next != null) {
			hb = hb.next;
			lenB++;
		}
		ha = headA;
		hb = headB;
		return getNode((lenA < lenB) ? hb : ha, (lenA < lenB) ? ha : hb, (lenA < lenB) ? lenB - lenA : lenA - lenB);

	}

	public ListNode getNode(ListNode l, ListNode s, int len) {
		for (int i = 0; i < len; i++) {
			l = l.next;
		}
		while (l != null) {
			if (l == s)
				break;
			l = l.next;
			s = s.next;
		}
		return l;
	}
}

解法二(双指针法):

双指针解法顾名思义需要两个指针,假设指针 pApB 分别指向链表 A 和链表 B 的头结点,之后两个指针分别以步幅为 1 的速度向链表的尾部遍历,当指针 pA 遍历到链表 A 的尾节点时,将指针 pA 指向链表 B 的头部。同样地,当指针 pB 遍历到链表 B 的尾节点时,将指针 pB 指向链表 A 的头部。当两个指针相遇时,指针 pA 或者 pB 所指向的节点就是两个链表的相交节点。

为了说明双指针的求解思路,假设链表 A 和链表 B 的结构如下图所示,

 

其中,链表 A 包含 6 个节点,节点的值分别为 1、3、5、7、9 和 11;链表 B 包含 4 个节点,节点的值分别为 2、4、9 和 11,因此,两个链表的相交节点为 9。设链表 A 中不相交的部分(即蓝色部分的节点)长度为 L1 L1 ,链表 B 中不相交的部分(即黄色部分的节点)长度为 L2 L2 ,两个链表相交的部分(即红色部分的节点)长度为 L3 L3 。

如下图所示,当指针 pB 遍历到链表 B 的尾节点 11 时,指针 pA 遍历到链表 A 中节点 7 的位置,下一次遍历指针 pB 将处于链表 A 的节点 1 的位置。

同理,当指针 pA 遍历到链表 A 的尾节点 11 时,此时指针 pB 处于链表 A 中节点 3 的位置,下一次遍历指针 pA 将处于链表 B 的节点 2 位置。

再经过两次遍历后,指针 pA 将位于链表 B 中节点 4 的位置,而指针 pB 也将到达链表 A 的节点 4 的位置,下一次遍历两个指针将在节点 9(即相交节点)相遇。此时,两个指针走过的长度都为 L1+L2+L3 L1+L2+L3 。究其原因,可以将两个指针走过的“路程”看成 3 个部分,即蓝色部分、红色部分以及橙色部分,只是两个指针走过 3 个部分的顺序是不同的,指针 pA 先走蓝色部分而指针 pB 先走橙色部分,但是经过前 3 个部分后,两个指针走过的长度一定是相同的,因此在下一次遍历的时候两个指针一定会相遇。

代码如下:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        
        ListNode pA = headA;
        ListNode pB = headB;
        while (pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }
        return pA;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值