python_ACM模式《剑指offer刷题》链表4

文章讲述了如何通过快慢指针算法在O(N)时间复杂度和O(1)空间复杂度下判断链表中是否存在环,并解释了快慢指针相遇原理。还提供了链表节点类定义和代码实现,以及示例应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

面试tips:

询问是否需要判断环,可微调下方代码。

思路:

思路一:

判断环是否存在:设定一快一慢指针,均从头节点出发,快指针一次走两步,慢指针一次走一步。若无环,则快指针会先到达空,返回False表示无环;若有环,则快慢指针必定相遇。前者无环快指针先到达空节点好理解,后者有环为什么快慢指针必定相遇呢?这里提供两种理解方式。

理解①:

理解②:

设慢指针刚进入环的第一个节点时,快指针(此时必定在环中)与慢指针中间相差n(n小于环的个数)个节点,则因为快指针每次走两步,慢指针每次走一步,因此快指针相对于慢指针而言快一步,因此在第n次时快指针追上慢指针。因此也是在慢指针的第一圈中被快指针追上。

               

若环存在,则寻找环的入口:

       

代码实现:

时复O(N),空复O(1)

class ListNode:
    def __init__(self, val, next = None):
        self.val = val
        self.next = next

def arr2List(arr, pos):
    prev = dummy_head = ListNode(0)
    entry = None
    for i in range(len(arr)):
        node = ListNode(arr[i])
        prev.next = node
        prev = prev.next
        entry = node if pos == i else entry
        if i == len(arr)-1:
            node.next = entry
    return dummy_head.next

def findcycle(head):
    # 找到环的入口
    # 1 先找到快慢指针相遇之处
    if not head: # 这里先排除掉空节点 是因为后面要fast.next 不能对空指针操作
        return -1
    left = fast = slow = head
    while fast.next and fast.next.next:
        fast = fast.next.next
        slow = slow.next
        if fast == slow:
            # 此时slow记录了相遇位置
            break
    if not fast.next or not fast.next.next:
        return -1
    # left和slow同时走直到相遇
    while left != slow:
        left = left.next
        slow = slow.next
    return left


if __name__ == '__main__':
    arr = [2, 6, 1, 5]
    pos = 1
    # pos表示环的入口索引,如果pos不为arr中的任一下标,则无环
    head = arr2List(arr, pos)
    result = findcycle(head)
    if result == -1:
        print('链表无环')
    else:
        print('环入口节点为:{}'.format(result.val))

参考资料:

1. 《剑指offer》

2. 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值