帶環鏈表問題 查找帶環鏈表的起始環節點

這個問題是 LintCode 上面的一個算法題目( 帶環鏈表 II ),主要考察的是對於鏈表,帶環鏈表的理解。

原問題描述:

給定一個鏈表,如果鏈表中存在環,則返回到鏈表中環的起始節點,如果沒有環,返回null。

樣例:

給出 -21->10->4->5, tail connects to node index 1,返回10
分析:
這個問題的思路主要分爲以下幾步:
1.判斷這個鏈表是不是帶環鏈表
2.如果是帶環鏈表,則返回環上的一個節點
3.從頭節點開始,一步一步往後挪動,每次都判斷節點是不是在環上面
判斷方法: 使得環上的節點繞環一週,如果遇到了測試節點,則說明測試節點是環上面的一個節點

如果繞完一週以後,一直沒有碰到測試節點,說明測試節點不是環上面的一個節點


解決代碼:

public class TestDetectCycle {
	public ListNode detectCycle(ListNode head){
		//如果存在循環體,則鏈的下一個節點是不會爲空的
		if (head == null || head.next == null) return null;
		//找到鏈上面的一個節點
		ListNode nodeInCycle = findANodeInCycle(head, head.next);
		//如果返回爲空,則說明沒有循環體
		if (nodeInCycle == null) return null;
		//將頭結點和環上面任意節點傳入,尋找起始點
		return findStart(head, nodeInCycle);
	}

	/**
	 * 在鏈表上的循環體內找到一個節點
	 * @param node1 每次跨度爲  1  的節點
	 * @param node2	每次跨度爲2的節點
	 * @return 返回的是循環體內的一個節點,如果沒有循環體,則返回null
	 */
	private ListNode findANodeInCycle(ListNode node1, ListNode node2) {
		//只有任意一個節點爲空,則說明沒有循環體,返回null
		if (node1 == null || node2 == null) return null;
		//說明兩個跨度不同的節點碰到了一起,那麼此時此時節點就在循環體內
		if (node1 == node2) return node1;
		//這是爲了防止下一行的代碼報空指針異常
		//只要某一個節點的下一個節點爲空,則說明沒有循環體
		if (node2.next == null) return null;
		//通過移動不同的跨度,尋找循環體
		return findANodeInCycle(node1.next, node2.next.next);
	}

	/**
	 * 尋找循環體的起始節點
	 * @param node	頭結點
	 * @param nodeInCycle	循環體上面的一個節點
	 * @return 返回其實節點
	 */
	private ListNode findStart(ListNode node, ListNode nodeInCycle) {
		while ( ! isStartNode(node, nodeInCycle)){
			//這個節點不是起始節點,則移動到下一節點,繼續驗證
			node = node.next;
		}
		return node;
	}

	private boolean isStartNode(ListNode node, ListNode nodeInCycle) {
		//爲了讓while循環體順利進行,一開始不能讓node2 == nodeInCycle,只要讓node2往後挪動一步就行了
		ListNode node2 = nodeInCycle.next;
		//while代碼段會讓node2繞着循環體跑一圈,如果能遇到node,說明node就在循環體上
		//如果繞完一圈後,還是沒有遇到node,說明node不在循環體上面
		while (node2 != nodeInCycle) {
			if (node == node2) return true;
			node2 = node2.next;
		}
		//因爲當尾部節點指向其自身的話,while中的循環體是不會進去的,因爲此時nodeInCycle == node2
		//這時只要判斷test節點node是不是等於nodeInCycle就行了
		return node == node2;
	}
}
關於判斷鏈表是否有環,更具體的請參考我的另一篇博客 帶環鏈表
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章