代码改变世界

【算法】链表判断是否有环

2021-07-01 16:22  .net小跟班(杜)  阅读(46)  评论(0编辑  收藏  举报
class ListNode{
    int val;
    ListNode next;
    ListNode(int x){
        this.val = x;
        next = null;
    }

思路一:用哈希表存储遍历所有节点

每个访问的节点,放入哈希表中,如果下一个节点已经存在于哈希表中,表示有环

时间和空间复杂度都是O(N)

//hash
    public boolean hasCycleWithHash(ListNode head){
        Set<ListNode> listNodeSet = new HashSet<>();
        while (head != null){
            if(!listNodeSet.add(head)){
               return true;
            }
            else {
                head = head.next;
            }
        }
        return false;
    }

思路二:快慢指针

同时出发,如果有环,跑的快的指针一定会和慢指针再次相遇

时间复杂度O(N),空间复杂度O(1)

//do while
    public boolean hasCycleWithFastSlow(ListNode head) {
        if (head == null || head.next == null){
            return false;
        }
        ListNode fast = head;
        ListNode slow = head;
        do {
 
            //判断前面的兔子有没有走到头,走到头,跳出循环
            if (fast == null || fast.next == null) {
                return false;
            }
            //自身移动
            slow = slow.next;
            fast = fast.next.next;
        } while (fast != slow);
 
        return true;
    }

换while结构,初始化slow和fast的差别

//while
    public boolean hasCycleMethod(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;
    }