面试算法之如何判断链表有环

如何判断链表有环

给一个单向链表,使用程序来判断链表中是否存在环结构。

private static class Node {
    int data;
    Node next;

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

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(isCycle1(node1));
    // 解法二
    System.out.println(isCycle2(node1));
    // 解法三
    System.out.println(isCycle3(node1));
}

解法一

解法一:依次遍历链表的节点,每遍历一个节点,就从头部开始检查到当前节点之前的所有节点,用当前节点和此节点之前的所有节点进行比较,如果存在相等的节点,则说明链表结构存在环,否则继续遍历节点,直到链表结束。

代码实现:

private static boolean isCycle1(Node head) {
    Node currentNode = head.next;
    int currentIndex = 1;
    while (currentNode != null) {
        Node node = head;
        int i = 0;
        while (node != null && i < currentIndex) {
            if (node == currentNode) {
                return true;
            }
            node = node.next;
            i++;
        }
        currentNode = currentNode.next;
        currentIndex++;
    }
    return false;
}

解法二

解法二:使用一个 HashSet 结构,从头开始遍历链表,每次遍历连接,使用当前节点去 HashSet 中获取节点元素,如果 HashSet 中不存在当前节点,则将当前节点存入 HashSet 容器中,如果 HashSet 中存在当前节点,说明链表存在环。

这其实是一种类似 Redis 中的布隆过滤器的结构。

代码实现:

private static boolean isCycle2(Node head) {
    Set<Node> set = new HashSet<>();
    while (head != null) {
        if (set.remove(head)) {
            return true;
        }
        set.add(head);
        head = head.next;
    }
    return false;
}

解法三

解法三:使用两个指针,让它们从头部开始遍历,其中一个指针每次遍历向后移动一个节点,另一个指针每次遍历向后移动两个节点,然后比较两个指针指向的节点是否相同。如果相同,则可以判断出链表有换,如果不同,则继续下一次循环。

代码实现:

private static boolean isCycle3(Node head) {
    Node p1 = head;
    Node p2 = head;
    while (p2 != null && p2.next != null) {
        p1 = p1.next;
        p2 = p2.next.next;
        if (p1 == p2) {
            return true;
        }
    }
    return false;
}

解法评估

-解法一解法二解法三
时间复杂度O(n^2)O(n)O(n)
空间复杂度O(1)O(n)O(1)

最后

本文Github https://github.com/herenpeng/code-learn 已收录,欢迎Star

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值