Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move duplicates to the end of a sorted array

I was asked this question in an interview. There is a sorted array with duplicates. The goal is to return the array with unique elements first and duplicates at the end preserving the order. For example [1, 1, 2, 3, 4, 4, 5] should become [1, 2, 3, 4, 5, 1, 4].

I was able to solve the question with an extra space (O(n) space) and linear time (O(n) time), but I am not sure if that is the best answer, ideally using no linear space.

I searched stackoverflow and found similar questions but not exactly the same. For example there was a question sorting an array and moving duplicates to the end, but in my case the array is already sorted and the goal is to only move duplicates to the end.

like image 701
apadana Avatar asked Sep 01 '18 00:09

apadana


People also ask

How do I remove duplicates from a sorted array?

Given a sorted array, remove all the duplicates from the array in-place such that each element appears only once, and return the new length. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Does sorting remove duplicates?

List. sort() does not remove duplicates.

How do I remove duplicates from a sorted array in Python?

We have to return the length of the array after removing all duplicate entries. We have to perform this in O(1) extra space. So we have to do the operation in-place. For an example, suppose A = [1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 5, 5, 5, 6] Then the output will be 6, as there are six distinct elements.

Does merge sort work with duplicates?

To use merge sort to remove duplicates, you would ignore elements that are repeated in the merging process. This reply answered the question recusively. take a look at the instructions for Mergesort.


Video Answer


2 Answers

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++;
    }
}
like image 150
Alireza Salimi Avatar answered Sep 20 '22 18:09

Alireza Salimi


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]
like image 31
MBo Avatar answered Sep 17 '22 18:09

MBo