如何判断单链表有环?

如题,如何判断单链表有环呢?

思路一:快慢指针,定义两个指针,同时指向链表头结点。指针移动速度不一样,一个快,一个慢,循环链表时,如果快慢指针相遇,则有环。很好理解,犹如跑道上的两个人,有人跑的快,有人跑的慢,同时起跑,跑的快的人,必然在比跑的慢的多跑一圈后,会追上跑得慢的。

思路二:遍历链表,每个元素都往set集合里装,如果有环,肯定会重复,新增元素时判断set是否包含该元素,即可判断链表是否有环:包含则有环,完成遍历,不包含则无环。

如图:

上代码:

定义链表节点

/**
 * 链表节点
 *
 * @author zab
 * @date 2022/5/19 22:54
 */
public class Node {
    public Object data;
    public Node next;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

}

 两种思路实现


/**
 * 链表环状检查工具
 *
 * @author zab
 * @date 2022/6/12 22:09
 */
public class ListCycleCheckUtil {

    private ListCycleCheckUtil(){}

    /**
     * 通过移动快慢指针判断链表是否有环
     * 为什么?快慢指针可以判断链表是否有环?
     * 因为两个人在操场跑步,跑的快的,在某一时刻会与跑的慢的相遇了,证明是环形跑道
     *
     * @author zab
     * @date 2022/6/12 23:02
     * @param head 链表头结点
     * @return true 有环
     */
    public static boolean hasCycle(Node head){
        if (head == null || head.getNext() == null) {
            return false;
        }

        Node fast;
        Node slow;

        fast = head;
        slow = head;
        while(true){
            fast = fast.getNext();

            if(fast == null){
                break;
            }

            fast = fast.getNext();
            slow = slow.getNext();

            if(fast == null){
                break;
            }
            if (fast == slow){
                return true;
            }

        }
        return false;
    }
    /**
     * 通过set判断链表是否有环,变量链表,不断往set集合加元素,如果发现有重复,就是环形
     *
     * @author zab
     * @date 2022/6/12 23:02
     * @param head 链表头结点
     * @return true 有环
     */
    public static boolean hasCycle1(Node head){
        if (head == null || head.getNext() == null) {
            return false;
        }
        HashSet<Node> nodes = new HashSet<>();
        Node temp = head;
        while(true){
            temp = temp.getNext();
            if(temp == null){
                break;
            }

            if (nodes.contains(temp)) {
                return true;
            }
            nodes.add(temp);
        }
        return false;
    }

    public static void main(String[] args) {
        Node test1 = new Node();
        test1.setData(1);
        Node test2 = new Node();
        test2.setData(2);
        Node test3 = new Node();
        test3.setData(3);
        Node test4 = new Node();
        test4.setData(4);
        Node test5 = new Node();
        test5.setData(5);
        Node test6 = new Node();
        test6.setData(6);

        test1.setNext(test2);
        test2.setNext(test3);
        test3.setNext(test4);
        test4.setNext(test5);
        test5.setNext(test6);
        test6.setNext(test3);


        boolean b = hasCycle1(test1);
        System.out.println(b);
    }
}

posted @   陈旭园  阅读(34)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示