求鏈表中環的入口節點

問題描述:一個鏈表中包含環,如何找到環的入口節點?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; } }
相關文章
相關標籤/搜索