关于单链表带环的一系列问题

题目

1、判断一个单链表是否带环
2、求取一个带环单链表的环的长度
3、求取一个带环单链表的环的入口
4、判断两个不带环单链表是否相交
5、求取两个不带环单链表的一个公共节点

这仅仅一个单链表是否带环可以拓展出这么多的问题,我们来一个一个解决
1、判断一个单链表是否带环。
思路
记得以前做过这个,可以用快慢指针,两个指针同时指向头结点,快指针一次走两个,慢指针一次走一个,如果慢指针最终追上快指针,说明链表有环,类似于两个人在操场跑步,一起开始跑,速度快的人必定会追上速度慢的。

代码
public static Boolean isHasCircle( LinkListNode head )
	{
		if(head==null) return null;
		LinkListNode fast=head;
		LinkListNode slow=head;
		Boolean flag = false;
		while(fast!=null && fast.next!=null )
		{
			fast = fast.next.next;
			slow = slow.next;
			if(fast == slow)
			{
				flag = true;
				break;
			}
		}
		return flag;
	}

2、求取一个带环单链表的环的长度
思路
当一个链表有环,快慢指针在某一个时刻必然会指向同一个节点,此时开始累加,下一次在相遇的时候,累加器的和便是环的长度,也就是慢指针走过的长度。

代码
public static int lengthCircleOfList(LinkListNode head)
	{
		if(head==null) return -1;
		int count=0;
		
		LinkListNode fast = head;
		LinkListNode slow = head;
		boolean flag =false;
		int sum = 2;    //判断是否为第二次相遇
		while(fast!=null && fast.next!=null)
		{
			fast = fast.next.next;
			slow = slow.next;
			if(fast == slow)
			{
				flag = true;
				sum--;
			}
			if(sum == 0)break;
			if(flag)
			{
				count++;
			}
		}
		
		return count;
	}


3、求取一个带环单链表的环的入口
思路
这里很巧妙,当快慢指针第一次相遇的时候,从相遇那个节点到环入口的节点和链表头结点到环入口的节点的距离相等,所以此时让一个指针从链头开始跑,一个指针从相遇的节点开始跑,那么相遇时,这个相遇节点便是环的入口节点。
那么会有一个问题:
这俩个距离为什么会相等,我们来证明一下。
当慢指针和快指针相遇的时候,快指针必然在环中转了n圈
所以有:2s = s + nr ;  s为慢指针走过的距离,r 为环的长度
可以得出  s = nr
假设环入口到相遇节点的距离为x,链头节点到环入口的距离为a,链表长度为L
所以有 x + a = s  ;由上面替换得到  x + a = nr   ==> x+ a =(n-1)r +r ==> x + a = (n-1)r +L - a 
所以有  a = (n-1)r +L - a - x;我们发现抛去转的圈数,刚好就是相遇节点到环入口的距离 == 链头节点到环入口的距离

代码
 public static LinkListNode theEnterOfList(LinkListNode head)
	{
		if(head==null) return null;

		LinkListNode fast = head;
		LinkListNode slow = head;
		while(fast!=null && fast.next!=null)
		{
			fast = fast.next.next;
			slow = slow.next;
			if(slow == fast)
			{
				break;
			}
		}
		fast = head;    //将快指针放到链头
		while(slow!=null && fast!=slow)   //相遇时跳出,此节点便是入口
		{
			fast=fast.next;
			slow = slow.next;
		}
				
		return slow;
	}


4、判断两个不带环单链表是否相交
5、求取两个不带环单链表的一个公共节点
思路
将第2条链表尾插到第1条链表,如果新链表有环,则证明两个链表相交
如果相交,则判断环入口,环入口即为两个链表的第一个公共节点

代码
 public static boolean isIntersect(LinkListNode head1,LinkListNode head2)
	{
		//将第2个链表尾插到第1个链表末尾
		LinkListNode p =head1;
		while(p.next!=null)
		{
			p=p.next;
		}
		p.next = head2;
		
		
//		LinkListNode temp = theEnterOfList(head1);	//第一个公共节点
//		System.out.println(temp.value);
		
		return  isHasCircle(head1);
	}

去掉上面的注释,即为打印第一个公共节点。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值