https://leetcode-cn.com/problems/circular-array-loop/
思路:用一个数组标记
i
i
i是否走过,然后对每个位置做一次循环模拟即可。但是这样复杂度是
O
(
n
2
)
O(n^2)
O(n2)的,事实上,对于上次遍历过的点,如果没有找到答案,那么这些点都是无解的,我们可以把它们剔除掉,这样可以把时间复杂度降低到
O
(
n
)
O(n)
O(n)。不过为了区分上次遍历和当前遍历,需要新开一个数组。
class Solution {
public:
bool circularArrayLoop(vector<int>& nums) {
int n=nums.size();
vector<bool> step(n);
bool ans=0;
for(int i=0;i<n&&!ans;i++)
{
if(step[i])
continue;
vector<bool> tmp(n);
tmp[i]=1;
int cur=i;
bool neg=nums[cur]<0;
while(1)
{
int nxt=((cur+nums[cur])%n+n)%n;
if(nxt==cur||step[nxt])
break;
if(tmp[nxt])
return 1;
if(neg&&nums[nxt]>0)
break;
if(!neg&&nums[nxt]<0)
break;
tmp[nxt]=tmp[cur];
cur=nxt;
}
for(int j=i+1;j<n;j++)
step[j]=step[j]||tmp[j];
}
return ans;
}
};
思路二:我们在一的基础上进行空间优化,只要把之前遍历过的点设置为一个这次无法达到的值,那么就可以不用开辟新的空间了。事实上,int数组比bool数组更加花费空间,不过int数组不仅可以判环,还可以计算长度。
class Solution {
public:
bool circularArrayLoop(vector<int>& nums) {
int n=nums.size();
vector<int> step(n);
for(int i=0;i<n;i++)
{
if(step[i])
continue;
step[i]=i+1;
int cur=i;
bool neg=nums[cur]<0;
while(1)
{
int nxt=((cur+nums[cur])%n+n)%n;
if(nxt==cur)
break;
if(step[nxt])
{
if(step[nxt]==step[cur])
return 1;
break;
}
if(neg&&nums[nxt]>0)
break;
if(!neg&&nums[nxt]<0)
break;
step[nxt]=step[cur];
cur=nxt;
}
}
return 0;
}
};