-3

This question is for real brainiacs, cause it should be done without an auxiliary array and has to be most efficient!

C program - needs to recieve an array with X numbers (suppose X=4 array : 5,4,3,2) and check if the array has all the numbers from 0 to X-1 (If X is 44 it needs to check if all numbers between 0 to 43 inside the array).

It has to be super efficient - I mean, running on the array 43 times is not an option!

Do you have any idea how to do this?? I'm trying to figure this one for hours without any success!!

It has to be O(n).

duedl0r
  • 9,289
  • 3
  • 30
  • 45
Sveta26
  • 541
  • 2
  • 8
  • 19

12 Answers12

2

If changing order of the array is allowed you can use in-place sort algorithm, then check if for some i:

array[i] == array[i+1]

Time complexity can be O(n*lg n) then.

zch
  • 14,931
  • 2
  • 41
  • 49
1

You can simplify the problem to finding duplicates.

Proof:

  • If the length of the array is not X => There are numbers missing. You can easily check that in O(1) or O(n).
  • Else => you have either all the correct numbers or there are duplicates.

Having that, you can use this implementation: Finding duplicates in O(n) time and O(1) space. Also make sure you check the bounds of the array. If the numbers are not inside the bounds, the array contains incorrect numbers.

This leads to an O(n) solution.

Community
  • 1
  • 1
duedl0r
  • 9,289
  • 3
  • 30
  • 45
  • You need an additional step: checking that there is no `i` such that `array[i] >= X || array[i] < 0`. – Peter T.B. Brett Jan 03 '12 at 10:39
  • http://en.wikipedia.org/wiki/Sorting_algorithm there is a section which describes integer sorting. – duedl0r Jan 03 '12 at 11:03
  • You only want the name? Don't you want to implement it? is it homework? :) I guess bucket sort does something very similar.. – duedl0r Jan 03 '12 at 12:01
1

Sort both arrays (is in O(n log n)). Then treat both arrays as queues:

  1. If the head elements of both queues are equal, print one of them and pop both.
  2. If the head elements are not equal, pop the smaller.
  3. Repeat.
thiton
  • 35,651
  • 4
  • 70
  • 100
0

You could sort the array, and then scan through it once. That should give you O(N log N) performance, better than the O(N^2) you'd need for the naive approach.

Chowlett
  • 45,935
  • 20
  • 116
  • 150
0

See some brilliant answers here, a C++ implementation of the @caf's answer could be bool stop=true; // first place the element i at location A[i], i.e 4 at A[4]

for(int  i = 0; i<n; i++) {
    while (A[A[i]] != A[i]){ 
        swap(A[i], A[A[i]])
    }
}
// than u can have the second loop which does the decision 
for(int  i = 0; i<n && !stop; i++) {
    if (A[i] != i){ 
        stop = true;
    }
}

if (stop)
    printf("duplicate");
else
   printf("not duplicate)
Community
  • 1
  • 1
Amit
  • 13,134
  • 17
  • 77
  • 148
  • it has to be O(n) or O(n+k) you got n^2 – Sveta26 Jan 03 '12 at 12:06
  • 1
    this link may help you... http://stackoverflow.com/questions/5739024/finding-duplicates-in-on-time-and-o1-space – Amit Jan 03 '12 at 12:08
  • I thing the first (@caf's) answer would be easier to implement by just replacing the print statement to an assignment to the bool variable `stop` which can be than used to determine the second loop's execution . – Amit Jan 03 '12 at 12:22
  • see my edited answer, He is not sorting he is just inserting i at location A[i], the trick in this solution is from your question..**an array of n elements which contains elements from 0 to n-1,** – Amit Jan 03 '12 at 12:32
0
foreach(int i in array)
{
    int count = 0;
    foreach(int i2 in array)
    {
        if(i == i2)
        {
            count++;
        }
    }
    if(count > 1)
    {
        return false;
    }
}

return true;
musefan
  • 47,875
  • 21
  • 135
  • 185
Volker Mauel
  • 514
  • 3
  • 21
0

an O(n) solution: The algorithm tries to put each element in the array onto its correct position, e.g. 1 onto a[0] and 2 onto a[1], by swapping with the element occupies the origin position.

at first, i = 1, a[i - 1] = 1, it's ok and nothing will be touched

i = 1
a = 1 6 3 4 5 7 1 

then, i = 2, a[i - 1] = 6 != 2, then swap a[i - 1] and a[6 - 1]

i = 2 
a = 1 7 3 4 5 6 1

then, i is still 2, but a[i - 1] == 7 != 2, then swap a[i - 1] and a[7 - 1]

i = 2
a = 1 1 3 4 5 6 7

now i = 2 but we see that a[i - 1] == a[1 - 1], thus we find the duplicate

full source:

#include <stdio.h>

int main() {
    int a[7] = {1, 6, 3, 4, 5, 7, 1};
    int i, t;
    for (i = 0; i < 7; ++i) {
        while (a[i] != i + 1) {
            if (a[i] == a[a[i] - 1]) {
                printf("duplicate: %d\n", a[i]);
                goto out;
            } 
            t = a[i];
            a[i] = a[a[i] - 1];
            a[t - 1] = t;
        }
    }
    printf("no duplicate\n");
out:
    return 0;
}
qiao
  • 17,941
  • 6
  • 57
  • 46
  • @Sveta26 I was assumming that the array is from 1 to n instead of from 0 to n - 1. These two codes seem to share the same idea. – qiao Jan 03 '12 at 12:56
0

You can use a modified merge operation (like the one used in mergesort) if the arrays are both sorted.

hugomg
  • 68,213
  • 24
  • 160
  • 246
0

You can do [on average case] better then the suggested O(nlogn) solution.
There is an O(n) armotorized average case solution using hash tables:

hash <- new hash set
for each e in A:
  hash.add(e)
for each e in B:
  if hash.contains(e): print e

You can overcome printing twice elements if they appear twice in B by storing an additional hash set of 'printed' elements.

If latency or worst case performacne is an issue, use one of the sort and iterate solutions suggested.

amit
  • 175,853
  • 27
  • 231
  • 333
0

Sort the smaller and use binary search to search it for each element in the larger. That way, you can do it in O((n1+n2)*log(n1)) where n1, n2 are the sizes of the arrays (n1 is the smaller).

jpalecek
  • 47,058
  • 7
  • 102
  • 144
-1

I don't understand what I'm missing in this question but AFAIK I don't see a reason why any (reasonable) solution should be anything more-/worse- than O(n) time (and space) complexity.

From the above comments and answers, I understand the following:

  • Negative numbers : I'm not sure whether negative numbers are allowed or not. The OP says check if all the array has all the numbers from 0 to X-1. So anything less than 0 is not expected in the array. So I assume negative numbers are not allowed
  • Duplicate numbers : referring to the same quote from the OP - check if all the array has all the numbers from 0 to X-1 I guess if X is the size of the array and all numbers from 0 to X-1 should be present, the I guess no duplicate numbers are allowed.

So making the above assumptions, we can use one bit to check whether i (0 <= i <= X-1) is present or not. If i is duplicate then it will fail mentioning that there is a duplicate number.

It scans the whole array one time - O(n) and just uses one bit per element, so X is 10 the X bits are needed - for example consider we need to handle 1000000 elements and sizeof(int) is 4 then we need 3.82M of memory to hold the array elements and only 0.48M is used for storing the presence of an element.

#include <stdio.h>

#define X 10
#define MIN 0
#define MAX X-1

int main(void)
{
    //int arr[X] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    //int arr[X] = {6, 7, 8, 9, 0, 5, 3, 2, 11, 12};
    //int arr[X] = {1, 1, 2, 4, 5, 6, 7, 8, 2, 2};
    int arr[X] = {1, 3, 2, 4, 5, 6, -7, 8, 2, 2}; 

    /* if X is more than sizeof(int) then change 
       the flag type to a wider one! */
    int flag = 0;

    int i;

    for(i=0 ;i<X ; i++) {
        if (arr[i] >= MIN && arr[i] <= MAX) {
            if (flag & 1<<arr[i]) {
                printf("Duplicate found : %d \n", arr[i]);
                return -1; 
            }   
            flag |= 1<<arr[i];
        } else {
            printf("Failure at %d : %d \n", i, arr[i]);
            return -1; 
        }   
    }   

    printf("Success \n");

    return 0;
}
Sangeeth Saravanaraj
  • 16,027
  • 21
  • 69
  • 98
  • DUPLICATES allowed but if there are duplicates that means that the function will be FALSE – Sveta26 Jan 03 '12 at 11:23
  • Sang, is that better than sorting and than checking if all numbers are inside? – Sveta26 Jan 03 '12 at 11:28
  • the givven array x will always contain numbers between 0 and x-1 – Sveta26 Jan 03 '12 at 11:30
  • @Sveta26 Sorting does not help here.. Any sorting will have to scan the whole array once. So the minimum time (or best time complexity) would be O(n). – Sangeeth Saravanaraj Jan 03 '12 at 11:59
  • @duedl0r I've already mentioned that in the program comment as a caution - `/* if X is more than sizeof(int) then change the flag type to a wider one! */` .. OTOH I'm not going to give 100% of answer as I want the original author to learn and understand `C`. Could you please reconsider the -1?! – Sangeeth Saravanaraj Jan 03 '12 at 12:01
  • @SangeethSaravanaraj: Do you know a type which is bigger than 64bit? If you use 64bit you can only store numbers up to 64. Or `X = 64`. This is not practical in any way.. what you have here is a bit array.. and additional arrays are not allowed. – duedl0r Jan 03 '12 at 12:07
  • @duedl0r This solution can be extended using `char[]` or the `flag` can be dynamically allocated based to the closest 8-multiple of the `X` using `malloc()`. For example, if `X` is `100` then allocate `100/8` bytes and store it as `flag`. But I don't want to give that answer to the OP as I want the OP author to learn and figure it out! .. Is that wrong?! – Sangeeth Saravanaraj Jan 03 '12 at 12:12
  • @SangeethSaravanaraj: In the title: "...without an additional array". You have an array. – duedl0r Jan 03 '12 at 12:14
-1

Read this for an answer - array validation - without using an auxiliary array

an array of n elements which contains elements from 0 to n-1, with any of these numbers appearing any number of times.

For example, let n be 7 and array be {1, 2, 3, 4, 5, 4, 6}, the answer should FALSE

Isn't the above statements contradict themselves?!

Community
  • 1
  • 1
Sangeeth Saravanaraj
  • 16,027
  • 21
  • 69
  • 98
  • the givven array x will always contain numbers between 0 and x-1 - in your previous answer you treated the array as it can have a number bigger than x-1..but the function i need will always have an array with x elements and no allemnt will be more than x-1 – Sveta26 Jan 03 '12 at 11:34
  • Why -1 without an explanation?! – Sangeeth Saravanaraj Jan 03 '12 at 13:03