問題描述:一個鏈表中包含環,如何找到環的入口節點?java
解法一:遍歷鏈表中的節點,將節點放入Set集合中,利用Set集合不容許插入重複數據的特性,能夠找到第一個重複的節點,即爲環的入口 節點。this
解法二:定義連個指針p1和p2,p1和p2都指向鏈表的頭結點,p1移動環的個數個節點,而後p1和p2以相同的速度移動,直到p1和p2相遇,相 遇的節點即爲環的入口節點。spa
package com.wyl.linklist; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; /** * 求鏈表中環的入口節點 * @author wyl * */ public class CircleStartNode { /** * 定義鏈表中節點的結構 * @author wyl */ static class Node<T>{ private T data ; //節點的值 private Node<T> next; public Node(T data){ this(data, null); } public Node(T data, Node<T> next) { this.data = data; this.next = next; } public T getData() { return data; } public void setData(T data) { this.data = data; } public Node<T> getNext() { return next; } public void setNext(Node<T> next) { this.next = next; } //節點的後繼節點 } public static void main(String[] args) { Node<Integer> n6 = new Node(6); Node<Integer> n5 = new Node(5, n6); Node<Integer> n4 = new Node(4, n5); Node<Integer> n3 = new Node(3, n4); Node<Integer> n2 = new Node(2, n3); Node<Integer> n1 = new Node(1, n2); n6.setNext(n3);
//Node n = circleStartNode(n1); Node n = circleStartNode2(n1); System.out.println(n.getData()); } /** * 查找環的入口節點 * 解法一:使用Set集合 * @param n1 * @return */ public static Node circleStartNode(Node<Integer> n1) { // TODO Auto-generated method stub if(n1 == null){ return null; } Set<Node> set = new HashSet<Node>(); while(n1 != null && set.add(n1)){ //利用set集合不能存儲重複數據的特性 n1 = n1.getNext(); } return n1; } /** * 解法二:使用兩個指針解決 * 一、首先獲得環中節點的個數 * 二、利用兩個指針進行查找 * @param n1 * @return */ public static Node circleStartNode2(Node<Integer> n1) { int size = circleSize(n1); //獲得環的節點個數 Node p1 = n1; Node p2 = n1; while(size > 0){ p1 = p1.next; size--; } while(p1 != null && p2 != null){ if(p1 == p2){ return p1; } p1 = p1.next; p2 = p2.next; } return null; } /** * 找到鏈表相遇的節點 * @param n * @return */ public static Node meetingNode(Node n){ if(n == null){ return null; } Node p1 = n; //慢指針,每次移動一個 Node p2 = n; //快指針,每次移動兩個 while(true){ p1 = p1.next; p2 = p2.next.next; if(p1 == p2){ //相遇的節點 return p1; } } } public static int circleSize(Node<Integer> n1) { int size = 0; if(n1 == null){ return -1; } //利用快慢指針獲得第一次相遇的節點,此節點必然在環中,而後遍歷進行計數 Node p = meetingNode(n1); Node p1 = p.next; while(p1 != null){ if(p1 != p){ size++; p1 = p1.next; }else{ size++; break; } } return size; } }