leetcode(141). Linked List Cycle

problem

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

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

solution

第一种解法不考虑使用额外空间,使用hash set判断是否出现重复的节点,判断是否有环。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        s = set()

        while head:
            if head in s:
                return True
            else:
                s.add(head)
                head = head.next
        return False

下面这种解法是不使用额外空间的,它的想法是使用两个指针,step1每次走一步,step2每次走两步,如果这两个指针可以碰上那么一定有环,否则一定无环。

证明:
不妨设整个链表就是一个环,step2领先step1 k步,设环中一共有n个元素,n步后有(step2 - step1) % n == 0,所以不会出现有环却检测不到的情况,即循环中step1 is step2是有环的充要条件。
反例如果step1和step3的话,在n为奇数时永远不会有(step2 - step1) % n == 0,step1 is not step2 列表却有环,不是充要条件。

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        step1 = head
        step2 = head

        while step1 and step2:
            step1 = step1.next
            tmp = step2.next
            if tmp:
                step2 = tmp.next
            else:
                return False
            if step1 is step2:
                return True

        return False

is和==的区别
is是比较两个对象的是否是同一个对象(id是否相同),而==则是比较两个对象的值是否相等(应该就是调用__eq__方法),这是需要自己去实现的(运算符重载),也就是说在自定义对象中即使两个不同实例的所有值都相同,如果没有定义__eq__方法的话还是会返回False,因为默认的__eq__应该就是return两者是否是同一个元素。
所以==是通过运算符重载来比较两个对象是否相等(实际上可以自定义各种操作,见下面代码示例),而is就是用来比较是否是同一个对象,通常is的速度要快一点。
所以这里我们要使用is来判断是否是一个对象,而不是使用==值是否相等(虽然题目中node也没实现__eq__,但还是要理解语言的细节)。

class N:
    def __init__(self, n):
        self.n = n
    def __eq__(self, N1):
        #return self.n == N1.n
        return True

n1 = N(1)
n2 = N(2)
#即使n1.n和n2.n不相等还是返回True
print(n1 == n2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值