Move duplicates to the end of a sorted array

You need to have 2-3 pointers (indexes). i: the next unique elements will be put at this position j: linear traversal pointer on the list

private static void fix(int[] nums) {
    int i = 0;
    int j = 0;
    while (j < nums.length) {
        int k;
        for (k = j + 1; k < nums.length && nums[k] == nums[j]; k++) {

        }

        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
        j = k;
        i++;
    }
}

If your values are in limited range, there exists solution in O(n) time and O(1) space.

Determine the maximum value in array. Get some constant C > arraymax, as example - C = 10 for your array.

Scan array, squeezing unique values and counting duplicates for every value. If value V has K>0 duplicates, write V+C*K instead of value.

At the next scan find values with duplicates, extract number of duplicates and write them after squeezed unique values.

def dedup(lst):
    mx = max(lst) + 1
    dupcnt = 0
    delcnt = 0
    start = 0
    for i in range(1, len(lst) + 1):
        if i == len(lst) or (lst[i] != lst[start]):
            lst[start - delcnt] = lst[start] + dupcnt * mx
            delcnt += dupcnt
            start = i
            dupcnt = 0
        else:
            dupcnt += 1
    dupidx = len(lst) - delcnt
    for i in range(0, len(lst) - delcnt):
        dupcnt = lst[i] // mx
        if dupcnt:
           lst[i] %= mx
           for j in range(dupidx, dupidx+dupcnt):
              lst[j] = lst[i]
           dupidx += dupcnt
    return lst

print(dedup([1,2,2,2,3,4,4,5]))
>>> [1, 2, 3, 4, 5, 2, 2, 4]