LeetCode 141. Linked List Cycle

首先吐槽一下这题目

Note that pos is not passed as a parameter.

样例

Input: head = [3,2,0,-4], pos = 1
Output: true

Input: head = [1,2], pos = 0
Output: true

Input: head = [1], pos = -1
Output: false

题目最后一句的 pos 让我百思不得其解,看了样例,我甚至觉得只用判断 pos 是否为 -1不就完事了,但是当我又看到传入参数没有 pos,我又懵了,直到我看了下题解,又尝试敲了如下代码并运行

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode head1 = head;
        int n = 0;
        while (n < 15) {
            int a = head1.val;
            System.out.print(a);
            head1 = head1.next;
            n++;
        }
        return true;
    }
}

在这里插入图片描述
看到 stdout 我才明白原来 pos 是给测试机用的,是让数组的最后一个元素指向下标为 pos 的元素,而不是给用户传参用的!

虽然题目本身不难,但是解题的方法似乎蛮有趣的,可以当拓宽思路的题

JAVA

① 存放到集合中

public class Solution {
    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;
    }
}

② 递归逐个删除

public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null)
            return false;
        if (head.next == head)
            return true;
        ListNode nextNode = head.next;
        head.next = head;
        return hasCycle(nextNode);
    }
}

我们只需要将每个 headnext 指向当前元素(自己),当往下递归时,只要存在环,那么总会遇到指向当前元素(自己)的 head

③ 先反转再比较

public class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode ans = null;
        while (head != null) {
            ListNode temp = head.next;
            head.next = ans;
            ans = head;
            head = temp;
        }
        return ans;
    }

    public boolean hasCycle(ListNode head) {
        ListNode rev = reverseList(head);
        if (head != null && head.next != null && rev == head) {
            return true;
        }
        return false;
    }
}

如果有环,那么链表反转之后,原来的头结点和反转之后的头结点一定是同一个,可以仔细想想链表反转的过程,head 一直往箭头方向前进,经过了一个环,必跟着箭头回到最初的起点

链表反转的基本用法可以看看这篇博客

④ 快慢指针(单双步)

public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == 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;
    }
}

慢指针每次前进一步,快指针每次前进两步,主要矛盾就在于快慢指针是否一定会相遇?会不会快慢指针每次都是擦肩而过,而不是正好在某一点重合?

解答:将慢指针看成相对静止的,那么快指针总会在某一时刻追上慢指针

⑤ 快慢指针(任意步)

当快慢指针速度差为 1 的时候,必会在环内相遇,速度差不为 1 的时候,可能会相遇,但不是任意速度组合都会相遇,与环长有关,数学证明涉及线性同余方程的解法

Python

① 存放到列表中

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        ans = []	# python列表,永远滴神
        while (head):
            if head in ans:
                return True
            else:
                ans.append(head)
                head = head.next
        return False

② 先反转再比较

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if not head or not head.next:
            return False

        ans, tmp = None, head
        while head != None:
            head.next, ans, head = ans, head, head.next

        return ans == tmp

③ 快慢指针(单双步)

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if not head or not head.next:
            return False
        
        slow = head
        fast = head.next

        while slow != fast:
            if not fast or not fast.next:
                return False
            slow = slow.next
            fast = fast.next.next
        
        return True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值