题目
难度:★★★☆☆
类型:数组
方法:快慢指针
力扣链接请移步本题传送门
更多力扣中等题的解决方案请移步力扣中等题目录
给定一个含有正整数和负整数的环形数组 nums。 如果某个索引中的数 k 为正数,则向前移动 k 个索引。相反,如果是负数 (-k),则向后移动 k 个索引。因为数组是环形的,所以可以假设最后一个元素的下一个元素是第一个元素,而第一个元素的前一个元素是最后一个元素。
确定 nums 中是否存在循环(或周期)。循环必须在相同的索引处开始和结束并且循环长度 > 1。此外,一个循环中的所有运动都必须沿着同一方向进行。换句话说,一个循环中不能同时包括向前的运动和向后的运动。
示例
示例 1:
输入:[2,-1,1,2,2]
输出:true
解释:存在循环,按索引 0 -> 2 -> 3 -> 0 。循环长度为 3 。
示例 2:
输入:[-1,2]
输出:false
解释:按索引 1 -> 1 -> 1 ... 的运动无法构成循环,因为循环的长度为 1 。根据定义,循环的长度必须大于 1 。
示例 3:
输入:[-2,1,-1,-2,-2]
输出:false
解释:按索引 1 -> 2 -> 1 -> ... 的运动无法构成循环,因为按索引 1 -> 2 的运动是向前的运动,而按索引 2 -> 1 的运动是向后的运动。一个循环中的所有运动都必须沿着同一方向进行。
提示:
-1000 ≤ nums[i] ≤ 1000
nums[i] ≠ 0
0 ≤ nums.length ≤ 5000
解答
环形数组的判断,建议使用快慢指针。
选取一个索引为起始位置,定义两个指针,慢指针slow每次走一步,快指针fast每次走两步,遍历过程中,查看能否相遇,如果可以相遇,则原数组可以组成环形数组循环。
这里需要注意的是两个特殊情况的判断,一个是快指针或慢指针遍历过程中所遇到的数字的符号需要一致,另一个是循环的长度必须大于1,这里循环的长度意思是慢指针走多少步可以回到最初的位置。
还有一点需要考虑的是,我们需要判断所有索引作为初始位置,只要有一个索引满足从该索引出发可以形成环形数组循环,直接返回True即可,这里需要注意是遇到的元素是0的情况,为了减少遍历,可以考虑将之前遍历走过的路程剔除出去,不需要再次考虑。
class Solution:
def circularArrayLoop(self, nums: List[int]) -> bool:
n = len(nums)
nxt = lambda x: (x + nums[x]) % n
for i in range(n):
if nums[i] == 0:
continue
slow = i
fast = nxt(i)
# 快慢指针
while nums[slow] * nums[nxt(slow)] > 0 and nums[fast] * nums[nxt(fast)] > 0:
if slow == fast:
if slow == nxt(slow):
break
else:
return True
slow = nxt(slow)
fast = nxt(nxt(fast))
# 访问过的置0
index = i
while nums[index] * nums[nxt(index)] > 0:
nums[index] = 0
index = nxt(index)
return False
有关更多力扣中等题的python解决方案,请移步力扣中等题解析