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:

  1. N is an integer within the range [1, 20,000].
  2. The elements of A are all distinct.
  3. Each element of A is an integer within the range [0, N-1].

这道题让我们找嵌套数组的最大个数,给的数组总共有n个数字,范围均在 [0, n-1] 之间,题目中也把嵌套数组的生成解释的很清楚了,其实就是值变成坐标,得到的数值再变坐标。那么实际上当循环出现的时候,嵌套数组的长度也不能再增加了,而出现的这个相同的数一定是嵌套数组的首元素,博主刚开始没有想清楚这一点,以为出现重复数字的地方可能是嵌套数组中间的某个位置,于是用个 set 将生成的嵌套数组存入,然后每次查找新生成的数组是否已经存在。而且还以原数组中每个数字当作嵌套数组的起始数字都算一遍,结果当然是 TLE 了。其实对于遍历过的数字,我们不用再将其当作开头来计算了,而是只对于未遍历过的数字当作嵌套数组的开头数字,不过在进行嵌套运算的时候,并不考虑中间的数字是否已经访问过,而是只要找到和起始位置相同的数字位置,然后更新结果 res,参见代码如下:

解法一:

class Solution {
public:
int arrayNesting(vector<int>& nums) {
int n = nums.size(), res = INT_MIN;
vector<bool> visited(n, false);
for (int i = ; 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 = ;
while (cnt == || i != start) {
visited[i] = true;
i = nums[i];
++cnt;
}
return cnt;
}
};

下面这种方法写法上更简洁一些,思路完全一样,参见代码如下:

解法二:

class Solution {
public:
int arrayNesting(vector<int>& nums) {
int n = nums.size(), res = INT_MIN;
vector<bool> visited(n, false);
for (int i = ; i < n; ++i) {
if (visited[nums[i]]) continue;
int cnt = , j = i;
while(cnt == || j != i) {
visited[j] = true;
j = nums[j];
++cnt;
}
res = max(res, cnt);
}
return res;
}
};

下面这种解法是网友 @edyyy 提醒博主的,可以优化解法二的空间,我们并不需要专门的数组来记录数组是否被遍历过,而是在遍历的过程中,将其交换到其应该出现的位置上,因为如果某个数出现在正确的位置上,那么它一定无法组成嵌套数组,这样就相当于我们标记了其已经访问过了,思路确实很赞啊,参见代码如下:

解法三:

class Solution {
public:
int arrayNesting(vector<int>& nums) {
int n = nums.size(), res = ;
for (int i = ; i < n; ++i) {
int cnt = ;
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

类似题目:

Nested List Weight Sum II

Flatten Nested List Iterator

Nested List Weight Sum

参考资料:

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

https://leetcode.com/problems/array-nesting/discuss/102432/C%2B%2B-Java-Clean-Code-O(N)

https://leetcode.com/problems/array-nesting/discuss/232283/C%2B%2B-straightforward-solution-beats-100

LeetCode All in One 题目讲解汇总(持续更新中...)

最新文章

  1. IIS短文件名泄露漏洞危害及防范方法
  2. 黑马程序员——【Java基础】——面向对象(一)概述、类与对象、继承、抽象类、接口、多态、内部类
  3. android 定时执行一个任务
  4. Linux ls -l内容详解
  5. php 短信网关短信内容不能有空格
  6. Injection Attacks-XML注入
  7. asp.net 输出 页面内容 在服务器上
  8. Python中几种数据结构的整理,列表、字典、元组、集合
  9. DEDE站点从网站根目录移到子目录
  10. MyEclipse导入主题文件epf后xml及jsp等页面中点击标签之后显示灰白
  11. HDU - 3697 Selecting courses
  12. V4L2驱动的移植与应用(三)
  13. yii2 or查询
  14. centos exfat格式U盘不支持问题
  15. AC自动机——1 Trie树(字典树)介绍
  16. 蓝牙 link timeout分析
  17. 树莓派上使用DHCPig进行DHCP池耗尽攻击
  18. gensim与numpy array 互转
  19. Mysql按数字大小排序String字段
  20. python 读写二进制文件实例

热门文章

  1. Unity Shader NPR 卡通渲染
  2. oracle使用sequence批量写数据
  3. perf性能调优
  4. k8s修改pod的hosts文件
  5. Kubernetes 有状态与无状态介绍
  6. 【01】Nginx:编译安装/动态添加模块
  7. WPF 开源框架项目介绍
  8. runtime template in vuejs
  9. java9模块不可见问题
  10. python从入门到放弃之进程