LeetCode-【模拟】环形数组是否存在循环

题目描述

在这里插入图片描述
测试用例

题目分析

总共分两步:

  • 第一步:将nums[i]转换为i的父亲节点列表,此操作可以使得后续找到的环满足k>1的条件
  • 第二步:遍历每个元素,对每个元素深度搜索,直到找到根节点或者环

几点说明:

  • 环分为有效环和无效环,环在nums[i]的原始值同号则为有效环
  • 为了避免对每个元素深度搜索,可以记录深度搜索的路径,同一路径上所有元素深度搜索的结果都相同,因此无需深度搜索同一路径上其他元素
  • 一个元素深度遍历后没找到有效路径,则把整个路径的元素nums[i]都设置为-1,无需再次遍历

需要用得到的数据结构有:

  • 栈(双端队列)
  • 标记数组(列表),用来标记当前元素曾经是否遍历到,若同一个路径上同一个元素两次被遍历,则存在环(有效环/无效环)

python实现

class Solution(object):
    def circularArrayLoop(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        # 备份nums
        nums_copy=[]                # nums_copy = nums 为引用
        for i in range(len(nums)):
            nums_copy.append(nums[i])

        length = len(nums)
        # 第一次遍历,nums[i]表示i的父亲节点
        for i in range(length):
            parents = nums[i]%length
            while parents<0:
                # 将所有负数转化为正数
                parents+=length
            if parents == 0:
                # nums[i] = -1 表示自身为根节点
                nums[i] = -1
            else:
                nums[i] = (parents+i)%length
        
        # 第二次遍历,深度搜索
        path = deque()          # 深度搜索的路径
        passed = [0]*length     # passed[i] = 1 表示i已经遍历过
        for i in range(length):
            while nums[i]!=-1:
                # 从i开始深度搜索,直到找到根节点或者环(有效环/无效环)
                if passed[i] == 1:
                    # 找到环
                    tmp = []    # 存放整个环
                    tmp.append(path.pop())
                    flag = nums_copy[tmp[-1]]   # flag = 0 表示环中异号
                    while tmp[-1] != i:
                        index = path.pop()
                        if nums_copy[index]*flag <= 0:
                            flag = 0
                        tmp.append(index)
                    if flag!=0:
                        # 存在有效环
                        return True
                    # (无效环)不是全正或者全负则跳出深度搜索
                    while tmp:
                        path.append(tmp[-1])
                        tmp = tmp[:-1]
                    break

                # 记录经过的位置
                path.append(i)
                passed[i] = 1
                i = nums[i]

            # 以i为起点经过的路径不存在有效环,无需再次访问
            while path:
                nums[path.pop()] = -1
        
        # 不存在有效环
        return False

代码性能

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值