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.html
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.git
Example 1:github
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個數字,範圍均在 [0, n-1] 之間,題目中也把嵌套數組的生成解釋的很清楚了,其實就是值變成座標,獲得的數值再變座標。那麼實際上當循環出現的時候,嵌套數組的長度也不能再增長了,而出現的這個相同的數必定是嵌套數組的首元素,博主剛開始沒有想清楚這一點,覺得出現重複數字的地方多是嵌套數組中間的某個位置,因而用個 set 將生成的嵌套數組存入,而後每次查找新生成的數組是否已經存在。並且還以原數組中每一個數字看成嵌套數組的起始數字都算一遍,結果固然是 TLE 了。其實對於遍歷過的數字,咱們不用再將其看成開頭來計算了,而是隻對於未遍歷過的數字看成嵌套數組的開頭數字,不過在進行嵌套運算的時候,並不考慮中間的數字是否已經訪問過,而是隻要找到和起始位置相同的數字位置,而後更新結果 res,參見代碼以下:post
解法一:優化
class Solution { public: int arrayNesting(vector<int>& nums) { int n = nums.size(), res = INT_MIN; vector<bool> visited(n, false); for (int i = 0; i < nums.size(); ++i) { if (visited[nums[i]]) continue; res = max(res, helper(nums, i, visited)); } return res; } int helper(vector<int>& nums, int start, vector<bool>& visited) { int i = start, cnt = 0; while (cnt == 0 || i != start) { visited[i] = true; i = nums[i]; ++cnt; } return cnt; } };
下面這種方法寫法上更簡潔一些,思路徹底同樣,參見代碼以下:url
解法二:spa
class Solution { public: int arrayNesting(vector<int>& nums) { int n = nums.size(), res = INT_MIN; vector<bool> visited(n, false); for (int i = 0; i < n; ++i) { if (visited[nums[i]]) continue; int cnt = 0, j = i; while(cnt == 0 || j != i) { visited[j] = true; j = nums[j]; ++cnt; } res = max(res, cnt); } return res; } };
下面這種解法是網友 @edyyy 提醒博主的,能夠優化解法二的空間,咱們並不須要專門的數組來記錄數組是否被遍歷過,而是在遍歷的過程當中,將其交換到其應該出現的位置上,由於若是某個數出如今正確的位置上,那麼它必定沒法組成嵌套數組,這樣就至關於咱們標記了其已經訪問過了,思路確實很贊啊,參見代碼以下:code
解法三:htm
class Solution { public: int arrayNesting(vector<int>& nums) { int n = nums.size(), res = 0; for (int i = 0; i < n; ++i) { int cnt = 1; while (nums[i] != i) { swap(nums[i], nums[nums[i]]); ++cnt; } res = max(res, cnt); } return res; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/565
相似題目:
參考資料:
https://leetcode.com/problems/array-nesting/
https://leetcode.com/problems/array-nesting/discuss/102432/C%2B%2B-Java-Clean-Code-O(N)