|
| 1 | +# 环形数组循环 |
| 2 | + |
| 3 | +### 题目描述 |
| 4 | + |
| 5 | +给定一个含有正整数和负整数的**环**形数组 `nums`。 如果某个索引中的数 k 为正数,则向前移动 k 个索引。相反,如果是负数 (-k),则向后移动 k 个索引。因为数组是环形的,所以可以假设最后一个元素的下一个元素是第一个元素,而第一个元素的前一个元素是最后一个元素。 |
| 6 | + |
| 7 | +确定 nums 中是否存在循环(或周期)。循环必须在相同的索引处开始和结束并且循环长度 > 1。此外,一个循环中的所有运动都必须沿着同一方向进行。换句话说,一个循环中不能同时包括向前的运动和向后的运动。 |
| 8 | + |
| 9 | + |
| 10 | +**示例 1** |
| 11 | + |
| 12 | +``` |
| 13 | +输入:[2,-1,1,2,2] |
| 14 | +输出:true |
| 15 | +解释:存在循环,按索引 0 -> 2 -> 3 -> 0 。循环长度为 3 。 |
| 16 | +``` |
| 17 | + |
| 18 | +**示例 2** |
| 19 | + |
| 20 | +``` |
| 21 | +输入:[-1,2] |
| 22 | +输出:false |
| 23 | +解释:按索引 1 -> 1 -> 1 ... 的运动无法构成循环,因为循环的长度为 1 。根据定义,循环的长度必须大于 1 。 |
| 24 | +``` |
| 25 | + |
| 26 | +**示例 3** |
| 27 | + |
| 28 | +``` |
| 29 | +输入:[-2,1,-1,-2,-2] |
| 30 | +输出:false |
| 31 | +解释:按索引 1 -> 2 -> 1 -> ... 的运动无法构成循环,因为按索引 1 -> 2 的运动是向前的运动,而按索引 2 -> 1 的运动是向后的运动。一个循环中的所有运动都必须沿着同一方向进行。 |
| 32 | +``` |
| 33 | + |
| 34 | +**提示** |
| 35 | + |
| 36 | +1. -1000 ≤ nums[i] ≤ 1000 |
| 37 | +2. nums[i] ≠ 0 |
| 38 | +3. 1 ≤ nums.length ≤ 5000 |
| 39 | + |
| 40 | +**进阶** |
| 41 | + |
| 42 | +你能写出时间时间复杂度为 **O(n)** 和额外空间复杂度为 **O(1)** 的算法吗? |
| 43 | + |
| 44 | + |
| 45 | +### 解题思路 |
| 46 | + |
| 47 | +**思路** |
| 48 | + |
| 49 | +若时间复杂度为 **O(n^2)** 则不用记录,双重遍历就完事了。降低时间复杂度为 **O(n)** 首先想到设置一个`visit`数组来记录是否被访问。若要空间复杂度为 **O(1)** ,考虑`-1000 ≤ nums[i] ≤ 1000`,可以用大于1000或小于-1000来记录是否被访问。需要注意的是循环长度要大于`1`,在一条链路中可能会出现`0 -> 2 -> 3 -> 3`这种在尾部存在的自循环。 |
| 50 | + |
| 51 | +**算法** |
| 52 | + |
| 53 | +**python** |
| 54 | + |
| 55 | +```python |
| 56 | +class Solution: |
| 57 | + def circularArrayLoop(self, nums: 'List[int]') -> 'bool': |
| 58 | + flag = 1000 |
| 59 | + lent = len(nums) |
| 60 | + drt = 1 # -1->left 1->right |
| 61 | + for loc in range(lent): |
| 62 | + if nums[loc] > 1000: |
| 63 | + continue |
| 64 | + if nums[loc] < 0: |
| 65 | + drt = -1 |
| 66 | + else: |
| 67 | + drt = 1 |
| 68 | + ct = (loc + nums[loc]) % lent |
| 69 | + flag += 1 |
| 70 | + nums[loc] = flag |
| 71 | + start = flag |
| 72 | + tmp = ct |
| 73 | + while -1000 <= nums[ct] <= 1000: |
| 74 | + if nums[ct] * drt < 0: |
| 75 | + break |
| 76 | + tmp = ct |
| 77 | + ct = (ct + nums[ct]) % lent |
| 78 | + flag += 1 |
| 79 | + nums[tmp] = flag |
| 80 | + else: |
| 81 | + if nums[ct] != nums[tmp] and nums[ct] >= start: |
| 82 | + return True |
| 83 | + return False |
| 84 | +``` |
0 commit comments