关于LeetCode中Linked List Cycle一题的理解

来源:互联网 发布:火星时代网络班 编辑:程序博客网 时间:2024/06/14 18:29

题目如下:

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

Follow up:
Can you solve it without using extra space?

     题目的要求是判断一个链表中是否存在环。这个题目我还是想了很久的,最开始的思路是判断随着指针节点移动,其必然会与开始节点即head节点重合,如果重合就说明这个链表是个圈。这个想法显然是考虑不周的,因为题目中问的是是否“包含”链表,而不是问如何验证这个链表是环形链表,所以这么做是有问题的。然后思路到这里就中断了很长时间,我就先回家压了压惊。晚上睡觉躺在床上的时候终于把问题想通了。我当时想到了钟表的指针,一个走得快一个走得慢,走得快的一定会在某个时刻追上走得慢的指针,这样两个指针看起来就重合了。所以说,这道问题中我们也可以设置两个指针一个走的快,一个走得慢,然后进行循环,如果走得快的指针和走得慢的指针在某一时刻能指向同一内存地址,就说明这个链表中存在一个环。如果链表中不存在环的话,说明可以将链表看做一条直线,走得快的链表是绝对可能与走的慢的链表指向重合的,而且会在一定时刻后指向null,说明已经到达了链表末尾,此时循环结束,程序直接返回false即可(返回false说明程序中不存在环)。思路我们终于明确了,下一步就是写代码了,注意一下边界条件的判定就好,已Accepted的代码如下所示:

<span style="font-size:14px;">    public boolean hasCycle(ListNode head) {        ListNode faster = head;        while(head!=null && faster!=null){            head = head.next;            if(faster.next!=null){              faster = faster.next.next;              }else{                return false;            }            if(head == faster){                return true;            }        }        return false;    }</span>
    这道题也是有Editoral Solution的,我们现在就一起来看一下这道题还有什么其他解法。Editoral Solution给出的第一种解法是使用HashSet的,每经过一个节点就将这个节点加入到HashSet中去,如果发现该节点已经在HashSet中了,说明这个节点之前已经到达过了,所以链表中肯定存在环,此时返回true即可。实现代码如下所示:

<span style="font-size:14px;">public boolean hasCycle(ListNode head) {    Set<ListNode> nodesSeen = new HashSet<>();    while (head != null) {        if (nodesSeen.contains(head)) {            return true;        } else {            nodesSeen.add(head);        }        head = head.next;    }    return false;}</span>
    该题另一种方法也是通过不同速度来判断是否有环的思路,刚才已经介绍过了,就不再赘述了,代码如下:

<span style="font-size:14px;">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;}</span>
    最后当然要给出这个Editoral Solution的地址了,其中还有一些内容是关于时间复杂度的分析,也是很重要的,地址在这里:https://leetcode.com/articles/linked-list-cycle/

    哈哈,那就愉快地结束了。


1 0
原创粉丝点击