Find all numbers disappeared in an array - Java, O(n) time, O(1) space

The idea of this algorithm is to:

  1. Put all numbers in correct positions, so basically sort the array but in a tricky way.
  2. Stop sorting when we've seen all elements. It means either every element is in the right place (value == index+1) or num[i-1] == 1 already which means we found a duplicate.
  3. Walk through the sorted array to find missing numbers.
    public List<Integer> findDisappearedNumbers(int[] nums) {
        /*
         0 1 2 3 4 5 6 7 - positions
        [4,3,2,7,8,2,3,1] - input array
         ^
         starts with position 0 and swap with the position where it belongs
        4<->7
        4 goes to the 3rd (array starts with 0) position and 7 from the 3rd position goes to the 0th position. 
        
        [7,3,2,4,8,2,3,1]
		Now put 7 in the 6th position where it belongs
		7<->3 (0th and 6th positions)		
		
        [3,3,2,4,8,2,7,1]
		3<->2 (0th and 2nd positions)
		
        [2,3,3,4,8,2,7,1]
        2<->3 (0th and 1st)

        [3,2,3,4,8,2,7,1]
        0th position is taken by 3. It should be put in the 2nd position but it's already taken by 3 which is correct. It's a duplicate, so skip it and check the next index.
        1st position already has 2 which is correct. Move on to the next index.
		2nd position already has 3 which is correct. Move on to the next index.
		3nd position already has 4 which is correct. Move on to the next index.
		5th position has 8 and 7th position doesn't have it, so swapping them.
		8<->1
		[3,2,3,4,1,2,7,8]
        Swapping 1 on the 4th position and 3 on the 0th position to put the 1 in the right place.
        3<->1        
		
        [1,2,3,4,3,2,7,8]
        At this point all elements are either in the right place or cannot be swapped as the target position already has the right element (duplicated elements).
        */
        List<Integer> missing = new ArrayList<>();
        if (nums == null || nums.length == 0) return missing;

        int i=0;
        int seen = 0;

        while (seen < nums.length) {
            if (nums[i] == i+1) {
                i = (i+1) % nums.length;
                seen++;
            } else {
                int j = nums[i] - 1;
                if (nums[i] == nums[j]) {
                    i = (i+1) % nums.length;
                    seen++;
                } else {
                    int tmp = nums[j];
                    nums[j] = nums[i];
                    nums[i] = tmp;
                }
            }
        }

		/*
		Compare
		[0,1,2,3,4,5,6,7]
		to 
		[1,2,3,4,3,2,7,8]
        and add missing elements to the result.
		*/
        for (int j=0; j<nums.length; j++) {
            if (nums[j] != j+1) missing.add(j+1);
        }

        return missing;
    }
Comments (1)