对于一个给定的链表,返回环的入口节点,如果没有环,返回null 
   拓展: 
   你能给出不利用额外空间的解法么? 
 package linkedlist;
/**
 * 题目描述: 链表的入环节点,如果无环,返回null
 * Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull.
 * Follow up: Can you solve it without using extra space?
 * 思路:
 * 1)首先判断是否有环,有环时,返回相遇的节点,无环,返回null
 * 2)有环的情况下, 求链表的入环节点
 *   fast再次从头出发,每次走一步,
 *   slow从相遇点出发,每次走一步,
 *   再次相遇即为环入口点。
 * 注:此方法在牛客BAT算法课链表的部分有讲解。
 */
//nowcoder pass
public class Solution {
	
    public ListNode detectCycle(ListNode head) {
    	if (head == null) {
    		return null;
    	}
    	
    	ListNode meetNode = meetingNode(head);
    	if (meetNode == null) {//说明无环
    		return null;
    	}
    	
    	ListNode fast = head;
    	ListNode slow = meetNode;
    	while (slow != fast) {
    		slow = slow.next;
    		fast = fast.next;
    	}
    	
    	return slow;
    }
    
    //寻找相遇节点,如果无环,返回null
    public ListNode meetingNode(ListNode head) {
    	ListNode slow = head;
    	ListNode fast = head;
    	while (fast != null && fast.next != null) {
    		slow = slow.next;
    		fast = fast.next.next;
    		if (slow == fast) {
    			return slow;
    		}
    	}
    	return null;
    }
}
来个不一样的思路:
1.首先判断是否存在环
2.若存在环,则从起点开始,每走一步就删除上一个节点的next指针,最后一个节点就是环的起点。因为环的起点会存在两个next指向它。
ListNode *detectCycle(ListNode *head) {//每次前进的时候删除上一个指针
        if(head==NULL||head->next==NULL)
            return NULL;
        ListNode*fast=head;
        ListNode*slow=head;
        while(fast!=NULL&&fast->next!=NULL){
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)
                break;
        }
         if(fast == NULL||fast->next==NULL)
            return NULL;
        ListNode * pre=head;
        ListNode*cur=head->next;
        while(cur!=NULL){
            if(pre==cur)
                return pre;
            pre->next=NULL;
            pre=cur;
            cur=cur->next;
        }
        return pre;
    }
                                                                                    
public class Solution {
    /*
     * 思路:
     * 1)首先判断是否有环,有环时,返回相遇的节点,无环,返回null
     * 2)有环的情况下,求链表的入环节点
     *    fast再次从头出发,每次走一步,slow从相遇点出发,每次走一步,再次相遇即为环入口点。
     */
    public ListNode detectCycle(ListNode head) {
        if(head == null) return null;
        
        ListNode slow = head;
        ListNode fast = head;
        ListNode meetNode = null;
        while(fast!=null && fast.next!=null) {
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast) { //快慢指针相遇,说明有环,记录相遇节点,跳出循环
                meetNode = slow;
                break;
            }
        }
        if(meetNode == null) return null; //相遇节点为空,说明无环,返回null
        
        fast = head; //fast再次从头出发
        while(slow != fast) { //再次相遇即为环入口点
            slow = slow.next; //slow每次走一步
            fast = fast.next; //fast每次走一步
        }
        return slow;
    }
} /**
思路:
1.还是先用快慢指针方法,找出快慢指针相遇的点;
2.重新定义两个指针,一个为head,另一个为快慢指针相遇点;
3.两个指针每次走一步,相遇点则是链表环的起点;
*/
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null){
            return null;
        }
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast){
                ListNode node1 = head;
                ListNode node2 = fast;
                while(node1 != node2){
                    node1 = node1.next;
                    node2 = node2.next;
                }
                return node1;
            }
        }
        return null;
    }
}
class Solution {public:ListNode *detectCycle(ListNode *head) {if(!head)return nullptr;if(!head->next)return nullptr;ListNode *pSlow = head;ListNode *pSlow2= head;ListNode *pFast = head;while(pFast&&pFast->next){pSlow = pSlow->next;pFast = pFast->next->next;if(pFast==pSlow)break;}if(!pFast||!pFast->next){//reach endreturn nullptr;}else{//loopwhile(pSlow2 != pSlow){pSlow2 = pSlow2->next;pSlow = pSlow->next;}return pSlow2;}}};
  ListNode *detectCycle(ListNode *h) {
        ListNode *p = h, *q = h; 
        while (q && q->next) {
            p = p->next;
            q = q->next->next;
            if (p == q) {
                while (h != q) {
                    q = q->next;
                    h = h->next;
                }
                return h;
            }
        }
        
        return NULL;
    }
# class ListNode: # def __init__(self, x): # self.val = x # self.next = None # # # @param head ListNode类 # @return ListNode类 # class Solution: def detectCycle(self , head ): # write code here if not head: return None slow = head fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: node1 = head node2 = slow while node1 != node2: node1 = node1.next node2 = node2.next return node1 return None
python版:
class Solution:
    def detectCycle(self , head ):
        if not head:
            return None
        slow = fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow is fast:
                slow = head
                while slow is not fast:
                    slow = slow.next
                    fast = fast.next
                return fast
        return None
                                                                                    class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
    	if(head == NULL)
    		return NULL;
    		
        ListNode *p = head, *q = head;
        while(q && q->next)
        {
        	p = p->next;
        	q = q->next->next;
			if(p == q)
			{
				while(q != head)
				{
					q = q->next;
					head = head->next;
				}
				return head;
			}
		} 
		return NULL;
    }
}; public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode p=head,q=head;
        if(p==null) return null;
        while(true){
            if(p.next==null) return null;
            else if(p.next.next==null) return null;
            p=p.next.next;
            q=q.next;
            if(p==q) break;
        }
        if(head.next==head) return head;
        for(q=head,p=head.next;p!=null;p=p.next){
            q.next=null;
            q=p;
        }
        return q;
    }
} /**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null)
            return null;
        ListNode fast = head;
        ListNode slow = head;
        boolean isRing = false;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(fast == slow){
                isRing = true;
                break;
            }  
        }
        if(!isRing)
            return null;
        fast = head;
        while(fast != slow){
            fast = fast.next;
            slow = slow.next;
        }
        return fast;    
    }
} 环儿的入口结点:从head起,第一个在环儿里的结点。 思路:爱的暴力转圈圈,时间复杂度O((n-m)*m),n=链表长度,m=环的长度;最坏接近O(n^2) 1)定义一对快慢指针,先让两个指针进入环中。 若指针走的过程中转角遇到空null结点,说明没有环,return null即可。唉!没找到爱的圈圈。 2)两个指针进入环中相遇后,进入下一步找环入口操作: 从head依次往后枚举判断当前枚举的结点是否在环中,判断方法: 让环中指针在环内转圈,若途中遇到了当前枚举的结点,说明该结点在环中。 找到第一个这样的结点就是入口结点。
public ListNode detectCycle(ListNode head) {
        if(head!=null){
            ListNode first=head,second=head.next,start;//定义指针
            //尝试把指针拉入环中
            while(first!=second){
                if(first==null||second==null||second.next==null) return null;//没环
                first=first.next;
                second=second.next.next;
            }
            //有环
            //找环入口:从head起依次往后枚举,第一个在环里的结点就是环的入口结点
            start=second;//标记环起点
            first=head;
            while(first!=null){
                //second指针在环里转一圈,查看当前结点first是否在环里
                do{
                    if(second==first) return first;//找到的第一个就是结果
                    second=second.next;
                }while(second!=start);//转一圈退出
                first=first.next;//枚举下一个
            }
            return null;
        }
        return null;
    } //思路:和判断是否有环解法一致,将遍历后的节点指向一个新增节点,如果遍历过程中,某个节点指向了那个节点,那么这个节点就是入口节点(即交叉点)。
public static ListNode detectCycle(ListNode head) { ListNode target = new ListNode(-1); ListNode cur = head; while(cur != null) { if(cur.next == target) { return cur; } ListNode next = cur.next; cur.next = target; cur = next; } return null; }
public class Solution {
    public ListNode detectCycle(ListNode head) {
        /* 快慢指针,第一次相遇快指针走过的是慢指针的两倍
         * head到环起始位置为l, 环周长为r, 第一次相遇点在环起点后x
         * s = l + x; 2s = l + r + x; => l + x = r; => l = r - x;
         * 同时从head和第一次相遇点往后走,相遇位置即为环起点
        */
        ListNode fast = head;
        ListNode slow = head;
        while(fast!=null&&fast.next!=null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                break;
            }
        }
        if(fast==null||fast.next==null) return null;
        slow = head;
        while(slow != fast){
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
} /** 一个新思路,可能没有满足不使用额外空间的要求,不过使用的也不多
    毕竟大多数牛友所述的Floyd判圆算法不是第一次就能够轻易想出来的
    1. 先利用快慢指针判断是否存在环,并在这个过程中对快指针走过的结点数计数,假设为2*count
    2. 从链表中第一个结点开始指定,依次让慢指针走2*count步,如果没有与指定结点相遇,就让指定结点向后移动
    3. 当第一次出现慢指针与指定结点相遇的情况时,该结点即为环入口,返回该结点即可
    */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode onestep=head;
        ListNode twostep=head;
        ListNode p=head;
        long count=0;
        while(twostep!=null && twostep.next!=null){
            onestep=onestep.next;
            twostep=twostep.next.next;
            count++;
            if(onestep==twostep){
                while(true){
                    for(int i=0;i<count*2;i++){
                        onestep=onestep.next;
                        if(onestep==p){
                            return p;
                        }
                    }
                    p=p.next;
                }
            }
        }
        return null;
    }
} 
class Solution { public: ListNode *detectCycle(ListNode *head) { if(head == NULL){ return 0; } ListNode* slow = head; ListNode* fast = head; while(fast != NULL && fast->next != NULL){ slow = slow->next; fast = fast->next->next; if(slow == fast){ break; } } if(fast == NULL || fast->next == NULL){ return NULL; } slow = head; while(slow != fast){ slow = slow->next; fast = fast->next; } return slow; } };