48.Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?
分析:题目要求判断返回一个链表中环的入口节点,没有入口节点话就返回null。

思路:Step1:首先根据Linked List Cycle判断是否有环,没有环的话就直接返回null;否则设快慢指针碰撞的节点为p,转Step2;

  Step2:如果有环,则假设慢指针走过的节点个数是s,则快指针走过的节点个数是2s;再假设环上的节点个数是c,则2s=s+nc(从这个地方也可以得到s = nc);再假设头结点到环的入口节点经过的节点个数是a(包括头结点和入口节点),假设入口节点.next到快慢指针碰撞点p上经过的节点个数是x,则a+x=s,进一步推导得a+x=nc ,  a=(n-1)c+c-x  ,其中(c-x)是p.next向后走到入口节点经过的节点个数,n表示大于1的整数。则头结点和p.next同时向后走,两个指针相遇的地方就是环的入口节点。

/*
	 *判断一个链表是否有环,有环的话输出入口节点 
	 */
	public ListNode detectCycle(ListNode head) {
		/*Step1:先找到链表中是否有环,有环的话通过快指针和慢指针找到其碰撞的节点*/
		 if(head == null || head.next == null){
	        	return null;
	        }
	        ListNode slow = head;
	        ListNode fast = head.next;
	        while(fast!=null && fast.next!=null){
	        	if(fast == slow){
	        		break;
	        	}
	        	fast = fast.next.next;//每次fast走两步,slow走一步,如果有环,则fast和slow一定相遇
	        	slow = slow.next;
	        }
	        
	        if(fast != slow){//fast不等于slow,说明没有环
	        	return null;
	        }else{
	        	/*Step2:找入口节点:头结点到入口节点的距离等于碰撞点的下一个节点p到入口点的距离+(n-1)c,其中c表中环的长度*/
	        	ListNode p = fast.next;//设置p为碰撞点的下一个节点
	        	ListNode h = head;
	        	
	        	while(h!=null && p!=null){
	 	        	if(p == h){
	 	        		break;
	 	        	}
	 	        	h=h.next;
	 	        	p = p.next;
	 	        }
	        	return h; 
	        }
    }


规整代码之后再次提交。

public ListNode detectCycle(ListNode pHead) {
       /*Step1:判断链表是否有环,有环的话则返回快慢指针的碰撞点,没有环的话则返回null*/
		ListNode meetNode = hasCycle(pHead);
		if(meetNode == null){
			return null;
		}
		/*Step2:找入口节点:头结点到入口节点的距离等于碰撞点的下一个节点p到入口点的距离+(n-1)c,其中c表中环的长度*/
    	ListNode p = meetNode.next;//设置p为碰撞点的下一个节点
    	ListNode h = pHead;
    	
         while(p != h){
	        	h=h.next;
		        p = p.next;
	        }
    	return h; 
    }
    
    /**
	 * 判断链表中是否有环。
	 * 有环的话返回快慢指针的碰撞点,没有环的话则返回null. 
	 */
	public ListNode hasCycle(ListNode head) {
        if(head == null || head.next == null){
        	return null;
        }
        ListNode slow = head;
        ListNode fast = head.next;
        while(fast!=null && fast.next!=null){
        	if(fast == slow){
        		break;
        	}
        	fast = fast.next.next;//每次fast走两步,slow走一步,如果有环,则fast和slow一定相遇
        	slow = slow.next;
        }
		return fast==slow?fast:null;
    }



网上有一篇不错的关于介绍链表中环相关问题的文章。http://blog.sina.com.cn/s/blog_725dd1010100tqwp.html


从另外一个角度,使用两个指针和环的节点个数来解决。

 /**
	 * 从另外一个角度考虑,继续使用两个指针的思想。
	 * 在找到碰撞点之后,可以计算得到环中结点的个数c,然后让p从头指针开始先走c步,然后q从头指针再与p一起向后走,
	 * p和q相遇的地方即为链表中环的入口点。
	 */
    public ListNode detectCycle(ListNode pHead) {
       /*Step1:判断链表是否有环,有环的话则返回快慢指针的碰撞点,没有环的话则返回null*/
		ListNode meetNode = hasCycle(pHead);
		if(meetNode == null){
			return null;
		}
		/*Step2:计算环中结点个数*/
    	ListNode p = meetNode.next;//设置p为碰撞点的下一个节点
    	int c = 1;
    	while(p != meetNode){
    		c++;
    		p = p.next;
    	}
    		
    	/*Step3:p从头指针先走c步,然后q从头指针开始和p一直走,相遇点即为环的入口点*/
    	p = pHead;
    	for(int i=0;i<c;i++){
    		p = p.next;
    	}
    	ListNode q = pHead;
    	while(p != q){
        	q=q.next;
	        p = p.next;
        }
    	return q; 
    }
    
    /**
	 * 判断链表中是否有环。
	 * 有环的话返回快慢指针的碰撞点,没有环的话则返回null. 
	 */
	public ListNode hasCycle(ListNode head) {
        if(head == null || head.next == null){
        	return null;
        }
        ListNode slow = head;
        ListNode fast = head.next;
        while(fast!=null && fast.next!=null){
        	if(fast == slow){
        		break;
        	}
        	fast = fast.next.next;//每次fast走两步,slow走一步,如果有环,则fast和slow一定相遇
        	slow = slow.next;
        }
		return fast==slow?fast:null;
    }



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值