【leetcode】141:环形链表
这题一看实在是太简单了,只要判断我们当前指针所在的元素是否已经被访问过就好。因此有第一种方法:
方法一:
使用数组储存我们访问过的所有元素,然后遍历我们访问过的所有元素和当前指针所在的元素进行比较,如果有地址一样的,就返回True说明是环形链表,不然就返回False,说明不是环形链表。时间复杂度为O(n^2)
代码如下:
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def hasCycle(self, head: ListNode) -> bool: node_list=[] while head!=None: if head in node_list: return True node_list.append(head) head=head.next return False
方法二:
弃用数组,改用哈希表来储存数据,查找的时间复杂度立刻降低为了O(1),总体的时间复杂度为O(n)。
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def hasCycle(self, head: ListNode) -> bool: seen = set() while head: if head in seen: return True seen.add(head) head = head.next return False
方法三:
使用快慢指针,如果有环形链表,那么快慢指针总会相遇,如果在相遇之前就已经走到了底,说明不是环形链表,时间复杂度为O(n),但是由于快慢指针可能要走2n个step,不用大O表示法的话,实际上会比哈希表稍微慢一些,代码如下:
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None 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
方法4:快慢指针的简单实现:
使用快慢指针还有一种实现手段,那就是直接将fast和slow指针进行比较,代码如下:
# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def hasCycle(self, head: ListNode) -> bool: slow=head fast=head #只用fast快指针进行判断是否到了终点,因为fast更快,所以只需要用fast指针即可 while fast and fast.next: slow=slow.next fast=fast.next.next if slow==fast: return True return False
在编写循环条件的时候,我们只需要判断快指针是否到了重点,由于可能fast.next.next为空,但是不能fast.next为空(这个为空,fast.next.next就无法执行,导致程序出错)。因此我们仅需要循环条件fast and fast.next进行判断就可以。