【13】Find the start of loop

Question:Given a circular linked list, implement an algorithm which returns node at the beginning of the loop.

DEFINITION:Circular linked list: A (corrupt) linked list in which a node’s next pointer points to an earlier node, so as to make a loop in the linked list.

EXAMPLE:Input: A -> B -> C -> D -> E -> C [the same C as earlier]  Output: C



思路:

1.判断一个链表是否有环的思路是设置两个指针都从链表头开始,指针1每次前进一步、指针2每次前进两步,如果两个指针最终指向同一个节点则该链表有环,否则无环。因为对于有环链表来说,n和2n实则是同一位置。

2.对于寻找环的开始处,按1所述,指针1和指针2最终会在环内相遇,假设环节点数为n,环开始点距链表头k,相遇点在n-x处(x即为离环开始点距离)。当指针1到达环开始处,指针2在环中已前进k。

3.假设从2的状态开始(即指针1进入环开始),当指针1前进n/2步时,指针2前进2*(n/2)=n步(即指针2刚好绕环一圈回到2中k处)。当指针1到达相遇点n-x处时,指针1共前进(n-x)-n/2=(n/2-x)步,则同时指针2前进2*(n/2-x)=(n-2x)步,此时指针1在n-x处,指针2在n-2x+k处。而按假设此时两者相遇,即n-x = n-2x+k,则可知x=k。即可知两者相遇点距环路开始点的距离与环路开始点与链表头距离相等

4.则此时将指针1退回至链表头,指针2仍在3的位置,两指针同时每次前进一步,当两者再次相遇时的位置即为环路的开始处,即为题中要求的位置。


package CareerCup;

public class FindStartOfLoop 
{
	public FindStartOfLoop(){}
	public Node find(LinkedList ll)
	{
		if(ll==null || ll.header==null) return null;
		Node loopStart = null;
		Node nodeSlow = ll.header;
		Node nodeFast = ll.header;
		
		while(nodeSlow!=null && nodeFast!=null)
		{
			nodeSlow = nodeSlow.next;
			
			if(nodeFast.next==null)
			{
				loopStart = null;
				break;
			}
			
			nodeFast = nodeFast.next.next;
			if(nodeSlow == nodeFast)
			{
				nodeSlow = ll.header;
				while(nodeSlow!=nodeFast)
				{
					nodeSlow = nodeSlow.next;
					nodeFast = nodeFast.next;
				}
				loopStart = nodeSlow;
				break;
			}	
		}
		
		return loopStart;
	}
	
	public static void main(String[] args)
	{
		int[] data = new int[]{1,2,3,4,5,3};
		LinkedList ll = new LinkedList();
		ll.creatLoop(data);
		System.out.println("The linkedlist:");
		for(int i=0;i<data.length;i++)
		{
			if(i!=data.length-1)
				System.out.print(data[i]+"->");
			else
				System.out.print(data[i]);
		}
		System.out.println();
		FindStartOfLoop fsl = new FindStartOfLoop();
		Node loopStart = fsl.find(ll);
		System.out.println("The start of loop:"+loopStart.data);
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值