iteration will not enter the if condition if there are duplicates. therefore the algorithm will work finitely. To explain it better . Take the case of your example [2, 2, 2, 2]
Now the condition is if ( num[i] != nums[nums[i]-1]). => replace i and will find both are equal i.e 2 == 2 , therefore it would not enter if but enter else and increment i.
This really looks confusing at first. Giving better variable names would be much easier to understand.
int sendNumberToIdx = nums[currentIdx] -1 ;
then if condition will look like if (nums[currentIdx] != nums[sendNumberToIdx]). ==> This is less confusing.
@Annabelle_Sun hope this helps.