此题和 041.First-Missing-Positive 的解法非常相似。题目的共同点是:数组的元素规定了是从1~N. 这就强烈暗示了,如果试图把正整数1~N顺次放入nums[1]~nums[N]中,那么没有被正确归位的那个元素(即nums[i]!=i)一定有“问题”。
对于“把正整数1~N顺次放入nums[1]~nums[N]中”的这种特殊的排序任务,有如下典型的时间复杂度o(n)、空间复杂度o(1)的方法:
遍历所有元素nums[i],发现如果nums[i]!=i时,说明当前的nums[i]这个数没有被放置在合适的顺序位置。于是交换nums[i]和nums[nums[i]]。这样做的结果是:把nums[i]放到了它应该在的位置(正确归位),同时nums[i]有了新的值,需要再重复判断、交换的过程。这样的步骤持续到 nums[i]==nums[nums[i]],这样就到了一个死循环,对于i这个位置就不能再做任何操作,于是跳过。
等到所有元素都遍历结束,那么所有元素就会被“力所能及”地归入了它们应该在的顺序位置。那么此时,对于那些nums[i]!=i的、没有正确归位的元素,在本题的题意下,就是那些重复的元素,可以轻易地挑出来。
还有一种比较花哨的解法。对于数值x,我们如何不通过extra space来记录它是否出现过呢?方法是将nums[x]上的数字变成负数来进行标记,注意我们并不关心nums[x]是多少。只关心nums[x]是负数时表示x曾经出现过,反之表示x还没出现过。
所以我们依次遍历数组里的每个数字abs(x),注意我们关心数值时必须看的是abs(x),因为x的符号可能被encode了其他含义(如上所说)。如果nums[abs[x]]<0,表示abs(x)曾经出现过,加入我们的答案中。反之,说明abs(x)第一次出现,所以我们将nums[abs(x)]标记为负数,以此留下这个标记。