标签:hash new inf 长度 时间 双指针 asc alt 解决
题目:
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:哈希表和双指针法:
哈希表
把节点挨个放到哈希表中,如果链表中有环,则某个节点必然重复出现。用HashSet中的contains判定
代码如下:
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public boolean hasCycle(ListNode head) { HashSet<ListNode> node=new HashSet<>(); //Hash表 while(head!=null){ if(node.contains(head)){ return true; } else{ node.add(head); head=head.next; } } return false; } }
复杂度分析:
时间复杂度:O(n),对于含有 n个元素的链表,我们访问每个元素最多一次。添加一个结点到哈希表中只需要花费 O(1)的时间。
空间复杂度:O(n),空间取决于添加到哈希表中的元素数目,最多可以添加 n 个元素。
双指针
我们想成小学中的追及问题,当两个人在一个体育场跑步时,特别地当两个人的速度不一致时,这两个人在某一个时间必然相遇。所以我们可以设置一个快慢指针在链表上跑,当快慢指针指向同一个节点时必然有环;
代码如下:
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public boolean hasCycle(ListNode head) { if(head==null || head.next==null){ return false; } ListNode low =head; ListNode fast=head.next; while(low!=fast){ if(fast==null || fast.next==null){ //这里主要为了防止下面fast=fast.next.next;出现空指针异常 return false; } else{ low=low.next; fast=fast.next.next; } } return true; } }
复杂度分析:
链表中不存在环:快指针将会首先到达尾部,其时间取决于列表的长度,也就是 O(n)。
链表中存在环:
我们将慢指针的移动过程划分为两个阶段:非环部分与环形部分:非环部分为N,环状部分为K;
近似于快指针多走了一圈环状部分
因此,在最糟糕的情形下,时间复杂度为 O(N+K),也就是 O(n)。
空间复杂度:O(1),我们只使用了慢指针和快指针两个结点,所以空间复杂度为 O(1)。
标签:hash new inf 长度 时间 双指针 asc alt 解决
原文地址:https://www.cnblogs.com/Yunus-ustb/p/12891704.html