8

We have an array and it is unsorted. We know the range is [0,n].

We want to remove duplicates but we cannot use extra arrays and it must run in linear time.

Any ideas? Just to clarify, this is not for homework!

8
  • I'm not entirely sure you can do this to be honest. I mean there is counting sort, but that requires additional space. Commented Mar 24, 2011 at 4:46
  • I'm with Mimisbrunnr -- I'm not sure this can be done. Googling suggests that using a hashmap (which probably isn't allowed, here) is the fastest, easiest way to do it; If there were a clever, linear-time algorithm that didn't require extra memory it would be easy to find. Commented Mar 24, 2011 at 4:53
  • Is this an array of ints? Can you reorder the array? Commented Mar 24, 2011 at 4:53
  • 1
    Yes, it is an array of ints. You can reorder the array as long as you finish with O(n) running time. Commented Mar 24, 2011 at 4:55
  • 1
    We know that all integers in the array are between 0 and n. Commented Mar 24, 2011 at 5:03

8 Answers 8

13

If the integers are limited 0 to n, you can move through the array, placing numbers by their indices. Every time you replace a number, take the value that used to be there and move it to where it should be. For instance, let's say we have an array of size 8:

-----------------
|3|6|3|4|5|1|7|7|
-----------------
 S

Where S is our starting point, and we'll use C to keep track of our "current" index below. We start with index 0, and move 3 to the 3 index spot, where 4 is. Save 4 in a temp var.

-----------------
|X|6|3|3|5|1|7|7|   Saved 4 
-----------------  
 S     C

We then put 4 in the index 4, saving what used to be there, 5.

-----------------
|X|6|3|3|4|1|7|7|   Saved 5
-----------------
 S       C

Keep going

-----------------
|X|6|3|3|4|5|7|7|   Saved 1
-----------------
 S         C

-----------------
|X|1|3|3|4|5|7|7|   Saved 6
-----------------
 S C

-----------------
|X|1|3|3|4|5|6|7|   Saved 7    
-----------------
 S           C 

When we try to replace 7, we see a conflict, so we simply don't place it. We then continue from the starting index S, increment it by 1:

-----------------
|X|1|3|3|4|5|6|7| 
-----------------  
   S           

1 is fine here, 3 needs to move

-----------------
|X|1|X|3|4|5|6|7|
-----------------
     S

But 3 is a duplicate, so we throw it away and keep iterating through the rest of the array.

So basically, we move each entry at most 1 time, and iterate through the entire array. That's O(2n) = O(n)

Sign up to request clarification or add additional context in comments.

7 Comments

This requires additional space in some cases. What if you have { 0, 1, 20 } as your array? then you need an array of size 20.
You probably also need to do compression of the array at the end by removing items that are marked with X above (i.e. -1 could be used to mark missing items). To remove items just go through all elements once and copy to last free space O(n) again.
@Mimisbrunnr Integers are limited from 0..n, where n is the size of the array
Or did I misread? I agree this won't work if n > the size of the array.
@Mimisbrunnr - If I understand problem correctly, for an array of size 3, you can only have values in range [0,3].
|
3
    void printRepeating(int arr[], int size)
{
  int i;
  printf("The repeating elements are: \n");
  for(i = 0; i < size; i++)
  {
    if(arr[abs(arr[i])] >= 0)
      arr[abs(arr[i])] = -arr[abs(arr[i])];
    else
      printf(" %d ", abs(arr[i]));
  }
}

Comments

3

Assume int a[n] is an array of integers in the range [0,n-1]. Note that this differs slightly from the stated problem, but I make this assumption to make clear how the algorithm works. The algorithm can be patched up to work for integers in the range [0,n].

for (int i=0; i<n; i++)
{
    if (a[i] != i)
    {
         j = a[i];
         k = a[j];
         a[j] = j;  // Swap a[j] and a[i]
         a[i] = k;
     }
 }

 for (int i=0; i<n; i++)
 {
     if (a[i] == i)
     {
        printf("%d\n", i);
     }
 }

1 Comment

in the second if it's an assignment operator instead of comparison
0

Can you sort? Sort with Radix Sort - http://en.wikipedia.org/wiki/Radix_sort with complexity O(arraySize) for given case and then remove duplicates from sorted array O(arraySize).

Comments

0

Walk through the array assign array[array[i]] = -array[array[i]]; if not negative; if its already negative then its duplicate, this will work since all values are within 0 and n.

Comments

0

Extending @Joel Lee's code for completion.

#include <iostream>
void remove_duplicates(int *a, int size)
{
  int i, j, k;
  bool swap = true;

   while(swap){
    swap = false;
    for (i=0; i<size; i++){
        if(a[i] != i && a[i] != a[a[i]]){
            j = a[i];
            k = a[j];
            a[i] = k;
            a[j] = j;
            swap = true;      
        }

    }
    }
}

int main()
{
    int i;
    //int array[8] = {3,6,3,4,5,1,7,7};
    int array[8] = {7,4,6,3,5,4,6,2};

    remove_duplicates(array, sizeof(array)/sizeof(int));

    for (int i=0; i<8; i++)
        if(array[i] == i)
            std::cout << array[i] << " ";

    return 0;
}

Comments

0

With ES6 I think this can be solved with only a few lines reducing the array into an object and then using object.keys to get array without duplicates. This probably takes more memory. I'm not sure.

I did it like this:

var obj = array.reduce(function (acc, elem) {
      acc[elem] = true;
      return acc;
    },{});
var uniqueArray = Object.keys(obj);

This has the added bonus (or disadvantage) of sorting the array. It works with strings too.

1 Comment

This definitely uses linear auxilliary space, which the questions asks not to
0

Use the array a a container with negative sign as an indicator, this will corrupt the input though.

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.