首页 > 试题广场 >

判断链表中是否有环

[编程题]判断链表中是否有环
  • 热度指数:530742 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
判断给定的链表中是否有环。如果有环则返回true,否则返回false。


数据范围:链表长度 ,链表中任意节点的值满足
要求:空间复杂度 ,时间复杂度

输入分为两部分,第一部分为链表,第二部分代表是否有环,然后将组成的head头结点传入到函数里面。-1代表无环,其它的数字代表有环,这些参数解释仅仅是为了方便读者自测调试。实际在编程时读入的是链表的头节点。

例如输入{3,2,0,-4},1时,对应的链表结构如下图所示:

可以看出环的入口结点为从头结点开始的第1个点(注:头结点为第0个结点),所以输出true。
示例1

输入

{3,2,0,-4},1

输出

true

说明

第一部分{3,2,0,-4}代表一个链表,第二部分的1表示,-4到位置1(注:头结点为位置0),即-4->2存在一个链接,组成传入的head为一个带环的链表,返回true           
示例2

输入

{1},-1

输出

false

说明

第一部分{1}代表一个链表,-1代表无环,组成传入head为一个无环的单链表,返回false           
示例3

输入

{-1,-7,7,-4,19,6,-9,-5,-2,-5},6

输出

true

说明:本题目包含复杂数据结构ListNode,点此查看相关信息
public boolean hasCycle(ListNode head) {
if(head == null){
return false;
}
ListNode pre = head,tail = head;
while(pre.next != null && pre.next.next!=null){
pre = pre.next.next;
tail = tail.next;
if(pre == tail){
return true;
}
head = head.next;
}
return false;
}
发表于 2025-06-25 09:49:36 回复(0)
import java.util.*;
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null){
            return false;
        }
        ListNode cycle = head;
        return hasCycle1(head, cycle.next,1);
    }

    public static boolean hasCycle1(ListNode headNext, ListNode cycleNode, int k) {
        if (headNext == null || cycleNode == null){
            return false;
        }
        ListNode headFirst = headNext;
        boolean flag = false;
        int i = 1;
        while (i <= k && headNext.next != null){
            if (i != 1 && headFirst == cycleNode){
                flag = true;
                break;
            }
            headFirst = headFirst.next;
            i++;
        }
        if (!flag){
            flag = hasCycle1(headNext, cycleNode.next, k+1);
        }
        return flag;
    }
}
解题思路:这个方法就是我首先假设环节点cycle是头结点head的下一个节点,
此时令k=1,表明我接下来只需要比对头结点head和环节点cycle,如果它们相等的话就表明头结点就是环节点,
不是的话令k+1,环节点cycle = cycle.next再进行遍历,
根据环链表的特性,遍历到最后肯定是会存在环节点和链表中的某个节点是相等的,为什么要引入k,是为了防止程序陷入死循环,k小了可能会遍历不到环节点,所以,每次就以k+1来进行递归,这样一来如果链表存在环,则一定会被有遍历到的时候

发表于 2025-04-23 10:39:15 回复(0)
public boolean hasCycle(ListNode head) {
        if (head == null) {
            return false;
        }
        // 标记节点
        final ListNode flag = new ListNode(-1);
        ListNode currentNode = head;
        while (currentNode != null){
            ListNode next = currentNode.next;
            if (next.next == flag){
                return true;
            }
            currentNode.next = flag;
            currentNode = next;
        }
        return false;
    }
发表于 2025-03-30 14:31:52 回复(0)
我用的 do while

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode quick,slow;
        if(head == null){
            return false;
        }
        quick = head;
        slow = head;

        do{
            if(slow == null || quick == null || quick.next == null){
                return false;
            }
            slow = slow.next;
            quick = quick.next.next;
        }while(quick != slow);
        return true;
    }
}

发表于 2025-03-05 17:34:59 回复(0)
快指针相对于慢指针快1步,快指针和慢指针距离为D,如果链表是环状的,那么快指针一定会逐渐追上慢指针。

public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null||head.next==null){
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while(slow!=null && fast!=null && fast!=slow) {
slow = slow.next;
fast = fast.next;
if(fast!=null){
fast = fast.next;
}
}
return slow==fast;
}
}
发表于 2025-02-26 19:18:40 回复(0)
单针对这道题有一个有趣的解法,有没有环,因为一共就 10000 个数据,因此只需要一直循环下去看循环的次数,如果超过了 10000 ,那一定是有环。(只是分享一种思路,在复杂度的表现上并不好)
public boolean hasCycle(ListNode head) {
    ListNode p = head;
    int i = 0;
    while (p != null) {
        if (i > 10000) {
            return true;
        }
        p = p.next;
        i++;
    }
    return false;
}


发表于 2024-09-27 10:44:08 回复(0)
破坏性查找最快
public boolean hasCycle(ListNode head) {
         ListNode const_tail = new ListNode(999);
         while(head != null){
            if(head.next == head) return true;
            if(head.next == const_tail)  return true;
            ListNode temp =  head;
            head = head.next;
            temp.next = const_tail;
         }
         return false;
    }

发表于 2024-08-16 14:47:55 回复(0)
import java.util.*;
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        // 左程云老师讲过类似的题,那道题是这道题的进阶问题,要求返回成环的结点
        // 采用快慢指针,快指针一次走两个结点,慢指针一次走一个结点,若二者能相遇,则有环,否则无环

        // 补充:若要求返回成环(相交)结点,那么在快慢指针相遇之后,令快指针返回head,降速成一次走一个结点
        // 当二者再次相遇的结点就是成环结点

        // 算法的时间复杂度O(N),额外空间复杂度O(1)

        // 1.先判断链表为空的情况
        if (head == null) {
            return false;
        }
        // 2.确定链表不为空
        ListNode fast = head;
        ListNode slow = head;

        do {
            // 3.如果链表是无环的,那么fast一定先走到null,直接return false即可
            if (fast.next == null || fast.next.next == null) {
                // 这里一定不会报空指针异常,因为先判断fast.next == null,若满足,则直接return false,不会继续判断后面
                return false;
            }
            // 4.快指针一次走两个结点,慢指针一次走一个结点
            fast = fast.next.next;
            slow = slow.next;
        } while(fast != slow);
        // 5.若因为fast == slow而结束循环,说明fast和slow二者相遇了,说明链表有环
        return true;
    }
}

发表于 2024-07-26 23:16:39 回复(0)
public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                return true;
            }
        }
        return false;
    }
}
发表于 2024-07-18 18:18:54 回复(0)
public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null) {
            return false;
        }
        if (head.val == 100001) {
            return true;
        }
        head.val = 100001;
        return hasCycle(head.next);
    }

遍历链表,走过设置一个不可能存在的值,直到遍历到这个值返回true,遍历到尾返回false
发表于 2024-07-14 19:33:07 回复(0)
//循环超过10000次说明有环
public class Solution {
    public boolean hasCycle(ListNode head) {
        int count=1;
        while(head!=null)
        {
            head=head.next;
            count++;
            if(count>10000)
                return true;
        }
        return false;
    }
}

发表于 2024-07-14 14:03:54 回复(0)
java的给我看笑了哈哈
编辑于 2024-03-08 15:36:31 回复(0)
import java.util.*;
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow=head;
        if(head==null){
            return false;
        }
        while(fast!=null&&fast.next!=null){  //如果没环的话快指针会先到链表尾
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                return true;
            }
        }
        return false;
    }
}

发表于 2023-10-11 14:11:51 回复(0)
只想说,这个题目表述真的太垃圾!读半天没读明白!直接简单写判断链表是否有环不就完了?说了一堆废话。而且这个题有bug
public class Main {
    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String input = null;
        while ((input = br.readLine()) != null) {
            String[] ss = input.split("}");
            int last = Integer.parseInt(ss[1].split(",")[1]);
            System.out.println(last != -1);
        }
    }
}

发表于 2023-09-22 18:45:36 回复(0)
public boolean hasCycle(ListNode head) {
    if (head == null) return false;
    ListNode slow = head;
    ListNode fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
        if (slow == fast)
            return true;
    }
    return false;
}

发表于 2023-09-06 17:14:52 回复(0)
public boolean hasCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        while(head != null){
            if(set.contains(head)){
                return true;
            }
            set.add(head);
            head = head.next;
        }
        return false;
    }
发表于 2023-08-10 16:17:27 回复(0)
public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null){
            return false;
        }
        List<ListNode> list = new ArrayList<>();
        while(head != null){
            if(list.contains(head)){
                return true;
            }
            list.add(head);
            head = head.next;
        }
        return false;
    }

发表于 2023-08-03 10:55:46 回复(0)
public boolean hasCycle(ListNode head) {
        //找环,快慢指针  终将相遇
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                return true;
            }
        }
        return false;
    }

发表于 2023-07-17 19:23:29 回复(0)