首页 > 试题广场 >

判断链表中是否有环

[编程题]判断链表中是否有环
  • 热度指数:513588 时间限制: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,点此查看相关信息
单针对这道题有一个有趣的解法,有没有环,因为一共就 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)
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 || head.next == null) {
            return false;
        }
        if (head.val == 100001) {
            return true;
        }
        head.val = 100001;
        return hasCycle(head.next);
    }
}

看评论学到了快慢指针,我用了下规则中|val| < 100000。如果再次遇到100001说明有换。
发表于 2023-07-11 08:07:50 回复(0)
判断给定的链表中是否有环。如果有环则返回true,否则返回false。用Java写代码回复我
gpt3.5:
以下是Java代码实现:
public boolean hasCycle(ListNode head) {
    if (head == null || head.next == null) {
        return false; }
    ListNode slow = head; ListNode fast = head.next; while (slow != fast) {
        if (fast == null || fast.next == null) {
            return false; } slow = slow.next; fast = fast.next.next; }
    return true; }

其中,ListNode是链表节点的定义,包含一个val属性和一个next属性,表示节点的值和下一个节点的指针。具体代码实现中,我们使用快慢指针的方法来判断链表是否有环。我们让一个指针slow每次移动一步,另一个指针fast每次移动两步,如果链表有环,那么fast指针最终会追上slow指针,从而形成一个循环。如果fast指针走到了链表的末尾,那么说明链表没有环。

发表于 2023-06-09 14:34:08 回复(1)
public class Solution {
    public boolean hasCycle(ListNode head) {
        int x = (int)1e5+1;
        while ( head != null ) {
            if ( head.val == x ) return true;
            head.val = x;
            head = head.next;
        }
        return false;
    }
}

发表于 2023-04-29 14:59:19 回复(0)
利用java的面对对象特性求题解, 遍历链表同时, 将每个节点存入list, 拿到当前节点时, 先判断list中是否包含此节点 , 如包含 , 则有环, 方法直接返回true .
遍历完链表则代表没有环,返回false . 核心是利用对象的唯一性进行比对;
import java.util.*;
public class Solution {
    public boolean hasCycle(ListNode head) {
        ArrayList<ListNode> list = new  ArrayList<ListNode>();
        while(head!=null){
            if(list.contains(head)){
                return true;
            }
            list.add(head);
            head = head.next;
        }
        return false;
    }
}

发表于 2023-02-28 13:53:16 回复(2)
不要想象得那么复杂,直接用hashCode + set也行。
import java.util.HashSet;
public class Solution {
    public boolean hasCycle(ListNode head) {
           
        HashSet<Integer> vals_hash = new HashSet<>();
        for(ListNode tmp = head;tmp != null;tmp = tmp.next){
            if(vals_hash.contains(tmp.hashCode())){
                return true;
            }
            vals_hash.add(tmp.hashCode());
       }
       return false;
    }
}


发表于 2022-12-22 16:28:28 回复(1)
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head==null||head.next==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;
    }
}

发表于 2022-11-22 20:27:47 回复(0)