【LeetCode】141. Linked List Cycle

问题

Given a linked list, determine if it has a cycle in it.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

思路

常规思路
遍历链表,遍历过的节点存起来,若next节点已经被遍历过,则存在环;时间复杂度=O(n),空间复杂度O(n)
代码

public boolean hasCycle_1(ListNode head) {
        if(head == null){
            return false;
        }
        Set<ListNode> nodeSet = new HashSet<>();
        ListNode f = head;
        while (f.next != null) {
            if (nodeSet.contains(f)) {
                return true;
            }
            nodeSet.add(f);
            f = f.next;
        }
        return false;
    }

优化解法
没必要将遍历过的节点都存起来,只要设置一个标志位即可。新建一个flagNode,遍历过的节点都指向它,节省存储空间;空间复杂度=O(1),但是坏处是修改了节点; 类似“过河拆桥”。

public boolean hasCycle_3(ListNode head) {
        if(head == null || head.next == null){
            return false;
        }
        ListNode flagNode = new ListNode(-1);
        ListNode f = head;
        while (f.next != null) {
            if (f.next == flagNode) {
                return true;
            }
            ListNode tmp = f;
            f = f.next;
            tmp.next = flagNode;
        }
        return false;
    }

更进一步,不修改节点数据,且空间复杂度为O(1)
意味着不能存储已经遍历过的节点,可以采用快慢指针法,若无环,则fast一定先到达null;若存在环,则fast一定会碰到 slow;fast 只要比slow快即可,这里用的是2倍速 vs 1倍速
代码

public boolean hasCycle_4(ListNode head) {
        if(head == null || head.next == null) {
            return false;
        }
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast != null && fast.next != null) {
            if(fast.next == slow || fast.next.next == slow){
                return true;
            }
            fast = fast.next.next;
            slow = slow.next;
        }
        return false;
    }

知识点

链表的遍历、快慢指针

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值