日拱一卒——Leetcode 141.环形链表

​ 大家好呀,今天为大家带来的LeetCode的题目是 leetcode 141、142两道关于环形链表的题目,由于解法十分相似就合在一起进行分析。

题目

image

分析

这个题目很简单,就是判断链表是否有环,算是在算法领域中属于入门较为初级的题目。对于这种判断链表是否有环,我们通常有一下四种方法:

  • 快慢指针:
  • 集合判重:
  • 逐一删除:
  • 先反转再比较:

下面就分别针对这四种解决方法进行阐述

解法一:快慢指针

对于链表判断成环,首先就会想到快慢指针的算法,即慢指针走一步,快指针走两步。看两者是否相遇,相遇则视为有环,不相遇则视为无环。代码也比较简单。

解法二:集合判重

链表有环,可以理解为有两个或多个节点的后序节点指向同一节点,此时我们就可以利用set集合来进行判重操作,遇到重复节点,就说明有环。

解法三:逐一删除

让链表从头节点,进行删除操作,所谓的删除,就是让他的next指向自己,如果链表中不存在换,那么从头节点一个个删除,最后肯定会删除完毕,如果存在环,就会出现head=head.next,因为在第一次遍历到这个节点的时候就已经指向自己了,后续再遍历到这个节点,就会发现它已经指向自己了。此时就可以判断为有环。

解法四:先反转再比较

由于链表反转以后,原来的头节点和反转以后的头节点一定是同一个,由此就可以判断是否存在环。

代码实现

解法一:快慢指针

 public boolean hasCycle(ListNode head) {
        if (head == null)
            return false;
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            //由于我们刚开始快慢指针都指向第一个,所有这边我们要先走
            slow = slow.next;
            //由于要走两步,所以在循环条件中就要保证fast.next也不为空
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }

解法二:集合判重

public boolean hasCycle(ListNode head) {
        //用set集合来判重
        Set<ListNode> set = new HashSet<>();
        while (head != null) {
            //重复说明有环
            if (set.contains(head))
                return true;
            //没重复就继续下一个
            set.add(head);
            head = head.next;
        }
        return false;
    }

解法三:逐一删除

public boolean hasCycle(ListNode head) {
        //head为空或者其后续节点为空表示遍历完了返回false
        if (head == null || head.next == null)
            return false;
        //其自身的后续节点是自己表示成环返回true
        if (head.next == head)
            return true;
        //重新创建一个ListNode用于递归调用,然后‘删除’该节点。
        ListNode nextNode = head.next;
        head.next = head;
        return hasCycle(nextNode);
    }

解法四:先反转后比较

    public ListNode reverseList(ListNode head) {
    //新链表
    ListNode newHead = null;
    while (head != null) {
        //第一步先保存下一个节点
        ListNode temp = head.next;
        //第二步把当前节点指向新链表
        head.next = newHead;
        //第三步开启新循环,新链表即为当前链表
        newHead = head;
        //第四步移动当前链表指向第一步保存的链表
        head = temp;
    }
    //返回新链表
    return newHead;
}

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

142.环形链表2

​ 其实实质上和141是一样的,就是需要注意的是要标记一下入环的第一个节点。

最后

  • 如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
  • 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
  • 如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。

image

猜你喜欢

转载自blog.csdn.net/issunmingzhi/article/details/108994475