# 565. Array Nesting

**<font color=red>难度: Medium</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/array-nesting/

> 内容描述

```
A zero-indexed array A of length N contains all integers from 0 to N-1. Find and return the longest length of set S, where S[i] = {A[i], A[A[i]], A[A[A[i]]], ... } subjected to the rule below.

Suppose the first element in S starts with the selection of element A[i] of index = i, the next element in S should be A[A[i]], and then A[A[A[i]]]… By that analogy, we stop adding right before a duplicate element occurs in S.

Example 1:
Input: A = [5,4,0,3,1,6,2]
Output: 4
Explanation: 
A[0] = 5, A[1] = 4, A[2] = 0, A[3] = 3, A[4] = 1, A[5] = 6, A[6] = 2.

One of the longest S[K]:
S[0] = {A[0], A[5], A[6], A[2]} = {5, 6, 2, 0}
Note:
N is an integer within the range [1, 20,000].
The elements of A are all distinct.
Each element of A is an integer within the range [0, N-1].
```

## 解题方案

> 思路 1
******- 时间复杂度: O(N^2)******- 空间复杂度: O(1)******

直接写了个暴力，超时
```
class Solution(object):
    def arrayNesting(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res = 1
        for i, num in enumerate(nums):
            length = 1
            start, nxt = num, nums[num]
            while nxt != start:
                length += 1
                nxt = nums[nxt]
            res = max(res, length)
        return res
```

> 思路 2
******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******

空间换时间，我们知道例子中的{A[0], A[5], A[6], A[2]} = {5, 6, 2, 0}，不管我们从{5, 6, 2, 0}中的哪一个开始，其实都是一样的结果，
所以我们记录一下访问过的点，遇到了跳过就可以了

beats 87.46%

```python
class Solution(object):
    def arrayNesting(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res = 1
        visited = set()
        for i, num in enumerate(nums):
            if num in visited:
                continue
            length = 1
            start, nxt = num, nums[num]
            while nxt != start:
                length += 1
                nxt = nums[nxt]
                visited.add(nxt)
            res = max(res, length)
        return res
```

> 思路 3
******- 时间复杂度: O(N^2)******- 空间复杂度: O(N)******

其实我们不需要额外空间来记录，我们只需要将原数组访问过的点设为-1就可以了，因为我们的数字范围是0到 N-1

但是要小心一个case，就是[0,1,2]这种所有数字都在本身index上的，这样我们还是需要check nxt != start的，因为没有任何数字被设为-1了

beats 100%

```python
class Solution(object):
    def arrayNesting(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res = 1
        for i, num in enumerate(nums):
            if num == -1:
                continue
            length = 1
            start, cur_idx, nxt = num, i, nums[num]
            while nxt != -1 and nxt != start: # latter check avoid case [0,1,2]
                nums[cur_idx] = -1
                cur_idx = nxt
                length += 1
                nxt = nums[nxt]
            res = max(res, length)
        return res
```


或者也可以用trick避免这种case,写成下面这样

```python
class Solution(object):
    def arrayNesting(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res = 1
        for i, num in enumerate(nums):
            if num == -1:
                continue
            length = 0
            start = num
            while nums[start] != -1: 
                tmp = start
                start = nums[start]
                length += 1
                nums[tmp] = -1
            res = max(res, length)
        return res
```



































