【算法】如何判断链表有环

268 阅读1分钟

有一个单向链表,链表当中有可能出现“环”,就像题图这样。如何用程序判断出这个链表是有环链表?

不允许修改链表结构。
时间复杂度O(n),空间复杂度O(1)。

记录两个算法

/**
 * 判断单链表是否存在环
 * @param head
 * @return
 */
public static <T> boolean isLoopList(ListNode<T> head){
	ListNode<T> slowPointer, fastPointer;
	
	//使用快慢指针,慢指针每次向前一步,快指针每次两步
	slowPointer = fastPointer = head;
	while(fastPointer != null && fastPointer.next != null){
		slowPointer = slowPointer.next;
		fastPointer = fastPointer.next.next;
		
		//两指针相遇则有环
		if(slowPointer == fastPointer){
			return true;
		}
	}
	return false;
}
/**
 * 找到有环链表的入口
 * @param head
 * @return
 */
public static <T> ListNode<T> findEntranceInLoopList(ListNode<T> head){
	ListNode<T> slowPointer, fastPointer;
	
	//使用快慢指针,慢指针每次向前一步,快指针每次两步
	boolean isLoop = false;
	slowPointer = fastPointer = head;
	while(fastPointer != null && fastPointer.next != null){
		slowPointer = slowPointer.next;
		fastPointer = fastPointer.next.next;
		
		//两指针相遇则有环
		if(slowPointer == fastPointer){
			isLoop = true;
			break;
		}
	}
	
	//一个指针从链表头开始,一个从相遇点开始,每次一步,再次相遇的点即是入口节点
	if(isLoop){
		slowPointer = head;
		while(fastPointer != null && fastPointer.next != null){
			//两指针相遇的点即是入口节点
			if(slowPointer == fastPointer){
				return slowPointer;
			}
			
			slowPointer = slowPointer.next;
			fastPointer = fastPointer.next;
		}
	}
	return null;
}