LeetCode Solutions

457. Circular Array Loop

Time: $O(n)$

Space: $O(1)$

			

class Solution {
 public:
  bool circularArrayLoop(vector<int>& nums) {
    const int n = nums.size();
    if (n < 2)
      return false;

    auto advance = [&](int i) {
      const int val = (i + nums[i]) % n;
      return i + nums[i] >= 0 ? val : n + val;
    };

    for (int i = 0; i < n; ++i) {
      if (nums[i] == 0)
        continue;
      int slow = i;
      int fast = advance(slow);
      while (nums[i] * nums[fast] > 0 && nums[i] * nums[advance(fast)] > 0) {
        if (slow == fast) {
          if (slow == advance(slow))
            break;
          return true;
        }
        slow = advance(slow);
        fast = advance(advance(fast));
      }

      slow = i;
      const int sign = nums[i];
      while (sign * nums[slow] > 0) {
        const int next = advance(slow);
        nums[slow] = 0;
        slow = next;
      }
    }

    return false;
  }
};
			

class Solution {
  public boolean circularArrayLoop(int[] nums) {
    if (nums.length < 2)
      return false;

    for (int i = 0; i < nums.length; ++i) {
      if (nums[i] == 0)
        continue;
      int slow = i;
      int fast = advance(nums, slow);
      while (nums[i] * nums[fast] > 0 && nums[i] * nums[advance(nums, fast)] > 0) {
        if (slow == fast) {
          if (slow == advance(nums, slow))
            break;
          return true;
        }
        slow = advance(nums, slow);
        fast = advance(nums, advance(nums, fast));
      }

      slow = i;
      final int sign = nums[i];
      while (sign * nums[slow] > 0) {
        final int next = advance(nums, slow);
        nums[slow] = 0;
        slow = next;
      }
    }

    return false;
  }

  private int advance(int[] nums, int i) {
    final int n = nums.length;
    final int val = (i + nums[i]) % n;
    return i + nums[i] >= 0 ? val : n + val;
  }
}
			

class Solution:
  def circularArrayLoop(self, nums: List[int]) -> bool:
    def advance(i: int) -> int:
      return (i + nums[i]) % len(nums)

    if len(nums) < 2:
      return False

    for i, num in enumerate(nums):
      if num == 0:
        continue

      slow = i
      fast = advance(slow)
      while num * nums[fast] > 0 and num * nums[advance(fast)] > 0:
        if slow == fast:
          if slow == advance(slow):
            break
          return True
        slow = advance(slow)
        fast = advance(advance(fast))

      slow = i
      sign = num
      while sign * nums[slow] > 0:
        next = advance(slow)
        nums[slow] = 0
        slow = next

    return False