索引从0开始长度为N的数组A,包含0到N - 1的所有整数。找到并返回最大的集合S,S[i] = {A[i], A[A[i]],
A[A[A[i]]], … }且遵守以下的规则。
假设选择索引为i的元素A[i]为S的第一个元素,S的下一个元素应该是A[A[i]],之后是A[A[A[i]]]…
以此类推,不断添加直到S出现重复的元素。
这道题我刚开始的思路是:
将得到的S的元素保存起来,然后每得到一个S的元素就遍历之前S得到的元素,判断有没有重复元素。这种运行起来比较费时间。
代码如下:
int arrayNesting(int* nums, int numsSize)
{
int i = 0;
int j = 0;
int b = 0;
int* arr = (int*)calloc(numsSize+1 , sizeof(int));//存放s元素
for (i = 0; i < numsSize; i++)
{
int a = i;//索引值
int count = 0;//记录s向arr中放了几个元素
while (1)
{
a = nums[a];
arr[count] = a;
for (j = 0; j < count; j++)//检查arr中是否有重复元素
{
if (arr[j] == a)
{
break;
}
}
if (arr[j] == a && count != 0 && j != count)
//跳出while循环条件 出现重复的元素,并且count不能等于0 且j不能等于count,
//当count = j时,说明上一个for循环没有找到重复的元素
{
break;
}
count++;
}
if (count > b)//保存最大的count值
{
b = count;
}
}
return b;
}
这道题还有以下三个限制条件。
注意: N是[1, 20,000]之间的整数。 A中不含有重复的元素。 A中的元素大小在[0, N-1]之间。
后来参考其他答案,又有了一种思路:
将A[i],A[A[i]] 等等全部改为-1,也就是将S的元素全部改为-1,因为N是整数,改为-1相当于标记,在比较的时候只用判断S元素的值是否为-1,就可以判断是否有重复元素。
代码如下:
int arrayNesting(int* nums, int numsSize)
{
int i = 0;
int max = 0;
int j = 0;
for (i = 0; i < numsSize; i++)
{
int count = 0;
for (j = i; nums[j] != -1;)
{
int ret = nums[j];
nums[j] = -1;
j = ret;
count++;
}
if (max < count)
{
max = count;
}
}
return max;
}
当时参考其他答案时,有一个问题一直想不明白,就是你将其元素改为-1,原数组的元素也会改变,是否会影响索引值不同时得到的S的元素集合。后来想了想不会影响,因为A中不含有重复元素,当S中有相同元素时,证明一个循环结束,相当于一个圈,不管你从圈上哪个位置开始,最后走的距离是一样的,比如,3-2-4-5-3和2-4-5-3-2,走的距离是一样的,而如果你不在这个圈里面,不管圈里面的数怎么变,都不会影响圈外的数。