判断链表是否有环、以及环长、入环点---java实现

首先:以下都是借鉴漫画算法-小灰的算法之旅一书的思路实现的哦,如有不对之处还请指正哈,谢谢!!!!
(1)判断链表是否有环:
解决思路:
p1节点和p2节点分别从头节点开始,
p1每次前进一个,p2每次前进2个
如果p1与p2可以相遇即代表链表有环

(2)前提是如果链表存在环,
环长确定思路:
环长 = 速度差 * 前进次数
p1与p2的相遇点开始,p1每次前进一个,p2每次前进2个,前进一次。计数一次,他俩再次相遇,计数器的值即为环长

(3)前提如果链表有环:
入环点确定思路:
p1从头节点开始,p2从相遇点开始,再次相遇点,即为入环点。

package com.example.demo.controller.algorithm;
public class ListIsCycle {
    
    

    public static Boolean isCycle(Node node){
    
    
        if(node == null){
    
    
            return null;
        }
        Node p1 = node;
        Node p2 = node;
        while (p1 != null && p2.next !=null){
    
    
            p1 = p1.next;
            p2 = p2.next.next;
            if(p1 == p2){
    
    
                //p1为相遇点
                System.out.println("链表的环长为:" + listCycleLength(p1));
                System.out.println("链表的入环节点地址为:" + cycleNode(node, p1));
                return true;
            }
        }
        return false;
    }

    /**
     * 判断环长----》前提是链表有环 -----》环长 = 每一次速度差 * 前进次数 = 前进次数
     * p2 比 p1 快一圈
     * @param node
     * @return
     */
    public static int listCycleLength(Node node){
    
    
        Node p1 = node;
        Node p2 = node;
        //环长初始为0
        int listCycleLength = 0;
        while (p1 != null && p2.next != null){
    
    
            p1 = p1.next;
            p2 = p2.next.next;
            listCycleLength++;
            if(p1 == p2){
    
    
                return listCycleLength;
            }
        }
        return listCycleLength;
    }


    /**
     * 确定如环节点
     * 原理:把其中一个节点放到头节点,另一个节点放在相遇节点,他们都每次前进一步,相遇点即为入环节点
     * @param root
     * @param meetNode
     * @return
     */
    public static Node cycleNode(Node root,Node meetNode){
    
    
        //根节点
        Node p1 = root;
        //首次相遇节点
        Node p2 = meetNode;
        while (p1 != null && p2 != null){
    
    
            p1 = p1.next;
            p2 = p2.next;
            if(p1 == p2){
    
    
                System.out.println("链表入环节点值为:"+p1.data);
                return p1;
            }
        }
        return null;
    }
    public static void main(String[] args) {
    
    
        Node node1 = new Node(5);
        Node node2 = new Node(3);
        Node node3 = new Node(7);
        Node node4 = new Node(2);
        Node node5 = new Node(6);

        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node2;

        System.out.println("链表是否存在环节点:"+isCycle(node1));

    }
}

class Node{
    
    
    int data;
    Node next;
    Node(int data){
    
    
        this.data = data;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42163781/article/details/107333582