class Solution {
public:
bool circularArrayLoop(vector<int>& nums) {
}
};
457. 环形数组是否存在循环
存在一个不含 0
的 环形 数组 nums
,每个 nums[i]
都表示位于下标 i
的角色应该向前或向后移动的下标个数:
nums[i]
是正数,向前(下标递增方向)移动 |nums[i]|
步nums[i]
是负数,向后(下标递减方向)移动 |nums[i]|
步因为数组是 环形 的,所以可以假设从最后一个元素向前移动一步会到达第一个元素,而第一个元素向后移动一步会到达最后一个元素。
数组中的 循环 由长度为 k
的下标序列 seq
标识:
seq[0] -> seq[1] -> ... -> seq[k - 1] -> seq[0] -> ...
nums[seq[j]]
应当不是 全正 就是 全负k > 1
如果 nums
中存在循环,返回 true
;否则,返回 false
。
示例 1:
输入:nums = [2,-1,1,2,2] 输出:true 解释:存在循环,按下标 0 -> 2 -> 3 -> 0 。循环长度为 3 。
示例 2:
输入:nums = [-1,2] 输出:false 解释:按下标 1 -> 1 -> 1 ... 的运动无法构成循环,因为循环的长度为 1 。根据定义,循环的长度必须大于 1 。
示例 3:
输入:nums = [-2,1,-1,-2,-2] 输出:false 解释:按下标 1 -> 2 -> 1 -> ... 的运动无法构成循环,因为 nums[1] 是正数,而 nums[2] 是负数。 所有 nums[seq[j]] 应当不是全正就是全负。
提示:
1 <= nums.length <= 5000
-1000 <= nums[i] <= 1000
nums[i] != 0
进阶:你能设计一个时间复杂度为 O(n)
且额外空间复杂度为 O(1)
的算法吗?
原站题解
javascript 解法, 执行用时: 56 ms, 内存消耗: 40.9 MB, 提交时间: 2023-06-13 14:31:02
/** * @param {number[]} nums * @return {boolean} */ var circularArrayLoop = function(nums) { const n = nums.length; for (let i = 0; i < n; i++) { if (nums[i] === 0) { continue; } let slow = i, fast = next(nums, i); // 判断非零且方向相同 while (nums[slow] * nums[fast] > 0 && nums[slow] * nums[next(nums, fast)] > 0) { if (slow === fast) { if (slow !== next(nums, slow)) { return true; } else { break; } } slow = next(nums, slow); fast = next(nums, next(nums, fast)); } let add = i; while (nums[add] * nums[next(nums, add)] > 0) { const tmp = add; add = next(nums, add); nums[tmp] = 0; } } return false; } const next = (nums, cur) => { const n = nums.length; return ((cur + nums[cur]) % n + n) % n; // 保证返回值在 [0,n) 中 }
python3 解法, 执行用时: 40 ms, 内存消耗: 16 MB, 提交时间: 2023-06-13 14:30:47
class Solution: def circularArrayLoop(self, nums: List[int]) -> bool: n = len(nums) def next(cur: int) -> int: return (cur + nums[cur]) % n # 保证返回值在 [0,n) 中 for i, num in enumerate(nums): if num == 0: continue slow, fast = i, next(i) # 判断非零且方向相同 while nums[slow] * nums[fast] > 0 and nums[slow] * nums[next(fast)] > 0: if slow == fast: if slow == next(slow): break return True slow = next(slow) fast = next(next(fast)) add = i while nums[add] * nums[next(add)] > 0: tmp = add add = next(add) nums[tmp] = 0 return False
golang 解法, 执行用时: 0 ms, 内存消耗: 1.9 MB, 提交时间: 2023-06-13 14:30:35
func circularArrayLoop(nums []int) bool { n := len(nums) next := func(cur int) int { return ((cur+nums[cur])%n + n) % n // 保证返回值在 [0,n) 中 } for i, num := range nums { if num == 0 { continue } slow, fast := i, next(i) // 判断非零且方向相同 for nums[slow]*nums[fast] > 0 && nums[slow]*nums[next(fast)] > 0 { if slow == fast { if slow == next(slow) { break } return true } slow = next(slow) fast = next(next(fast)) } add := i for nums[add]*nums[next(add)] > 0 { tmp := add add = next(add) nums[tmp] = 0 } } return false }
java 解法, 执行用时: 0 ms, 内存消耗: 39 MB, 提交时间: 2023-06-13 14:30:21
class Solution { public boolean circularArrayLoop(int[] nums) { int n = nums.length; for (int i = 0; i < n; i++) { if (nums[i] == 0) { continue; } int slow = i, fast = next(nums, i); // 判断非零且方向相同 while (nums[slow] * nums[fast] > 0 && nums[slow] * nums[next(nums, fast)] > 0) { if (slow == fast) { if (slow != next(nums, slow)) { return true; } else { break; } } slow = next(nums, slow); fast = next(nums, next(nums, fast)); } int add = i; while (nums[add] * nums[next(nums, add)] > 0) { int tmp = add; add = next(nums, add); nums[tmp] = 0; } } return false; } public int next(int[] nums, int cur) { int n = nums.length; return ((cur + nums[cur]) % n + n) % n; // 保证返回值在 [0,n) 中 } }
cpp 解法, 执行用时: 4 ms, 内存消耗: 7.1 MB, 提交时间: 2023-06-13 14:30:09
// 快慢指针 class Solution { public: bool circularArrayLoop(vector<int>& nums) { int n = nums.size(); auto next = [&](int cur) { return ((cur + nums[cur]) % n + n) % n; // 保证返回值在 [0,n) 中 }; for (int i = 0; i < n; i++) { if (!nums[i]) { continue; } int slow = i, fast = next(i); // 判断非零且方向相同 while (nums[slow] * nums[fast] > 0 && nums[slow] * nums[next(fast)] > 0) { if (slow == fast) { if (slow != next(slow)) { return true; } else { break; } } slow = next(slow); fast = next(next(fast)); } int add = i; while (nums[add] * nums[next(add)] > 0) { int tmp = add; add = next(add); nums[tmp] = 0; } } return false; } };