判断两个单向链表是否相交

1.分析问题:

链表分为有环和无环,如果两个链表存在相交,则只有两种可能,两个链表都无环或者都有环。
下面分别讨论。

2.判断链表是否有环

2.1定义链表
	//单向链表
	public static class LinkNode{
		int data;
		LinkNode next = null;
		public LinkNode(int data) {
			this.data = data;
			next = null;
		}	
	}
2.2判断是否有环

判断是否有环,有环返回入口点,无环返回null。

	public static LinkNode isLoop(LinkNode node) {
		if (node == null) {
			return null;
		}
		LinkNode slow = node;
		LinkNode fast = node;
		while(slow.next!=null && fast.next!=null) {
			//一次走一步
			slow = slow.next;
			//一次走两步
			fast = fast.next;
			if (fast!=null) {
				fast = fast.next;
			}
			/**
			 * 特别注意:
			 * 如果存在循环,则在慢指针走完环前,总会和快指针相遇,因为快指针比慢指针快一倍哦
			 * 从头指针和相遇点同时向后走,相遇的点必定是入口点。(这里要好好思考一下)
			 * 比如起点是A,入口点B,相遇点C,环一圈距离记为L,相遇是快指针比慢指针多走一圈,故AC = L,
			 * AC - BC = L - BC,所以AB = L - BC,即下次相遇的点必定是入口点B
			 */
			if (slow == fast) {//说明有环
				fast = node;//回到头指针
				while(slow!=fast) {
					fast = fast.next;
					slow = slow.next;
				}
				return slow;
			}
		}
		return null;
		
	}

3.无环链表相交情况

NOLOOP
两个无环链表比较,返回第一个交点,不相交返回null


	private static LinkNode getNoLoop(LinkNode head1, LinkNode head2) {
		int len1 = 1;//第一个链表长度
		int len2 = 1;//第二个链表长度
		LinkNode temp1 = head1;
		LinkNode temp2 = head2;
		//第一个链表的最后一个元素
		while(temp1.next!= null) {
			temp1 = temp1.next;
			len1++;
		}
		//第二个链表的最后一个元素
		while(temp2.next!= null) {
			temp2 = temp2.next;
			len2++;
		}
		//尾部不同,没有相交的点
		if (temp1.data !=temp2.data) {
			return null;
		}
		//相交情况
		int cur = Math.abs(len1-len2);//长度差
		//temp1记录长的链表,temp2记录短的链表
		if (len1>len2) {
			temp1 = head1;
			temp2 = head2;
		}else {
			temp1 = head2;
			temp2 = head1;
		}
		for (int i = 0; i < cur; i++) {
			temp1 = temp1.next;
		}
		//判断链表是否相同,相同则停止循环(这里指两个链表各个节点数据是否相同,
		//不是链表是否相同,这里省略比较
		while(temp1!=temp2) {
			System.out.println(temp1.data+ " "+ temp2.data);
			temp1 = temp1.next;
			temp2 = temp2.next;
		}
		return temp1;
	}

4.有环链表相交情况

有环链表相交分两种情况:
case1:入口点相同(可转化为无环)
case2:入口点不同
在这里插入图片描述
分别讨论:

	private static LinkNode getBothLoop(LinkNode head1, LinkNode loop1, LinkNode head2, LinkNode loop2) {
		if (loop1 == loop2) {//入口点相同,在环外找(包括环的入口点)
			int len1 = 1;//第一个链表长度
			int len2 = 1;//第二个链表长度
			LinkNode temp1 = head1;
			LinkNode temp2 = head2;
			//第一个链表的最后一个元素
			while(temp1.next!= loop1) {
				temp1 = temp1.next;
				len1++;
			}
			//第二个链表的最后一个元素
			while(temp2.next!= loop2) {
				temp2 = temp2.next;
				len2++;
			}
			//相交情况
			int cur = Math.abs(len1-len2);//长度差
			//temp1记录长的链表,temp2记录短的链表
			if (len1>len2) {
				temp1 = head1;
				temp2 = head2;
			}else {
				temp1 = head2;
				temp2 = head1;
			}
			for (int i = 0; i < cur; i++) {
				temp1 = temp1.next;
			}
			while(temp1!=temp2) {
				temp1 = temp1.next;
				temp2 = temp2.next;
			}
			return temp1;
		}else {//入口点不同(在环上找)
			LinkNode cur = loop1.next;
			while(cur!=loop1) {//遍历环上所有节点
				if (cur != loop2) {
					cur = cur.next;
				}else {
					return loop1;
				}
			}
			return null;
		}
	}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值