2012-03-12 3 views
11

Oggi un'intervistatore mi ha fatto questa domanda. La mia risposta immediata è stata che potevamo semplicemente fare una ricerca lineare, confrontando l'elemento corrente con l'elemento precedente nell'array. Poi mi ha chiesto come si potrebbe risolvere il problema in un tempo non lineare.In un tempo inferiore al lineare, trova il duplicato in un array ordinato

Ipotesi

  • L'array è ordinato
  • C'è solo uno duplicare
  • La matrice è solo popolato con i numeri [0, n], dove n è la lunghezza del array.

Esempio matrice: [0,1,2,3,4,5,6,7,8,8,9]

ho tentato di trovare una divide et impera algoritmo per risolvere questo problema, ma non sono sicuro che sia stata la risposta giusta. Qualcuno ha qualche idea?

+1

l'esempio include solo numeri '[0, n-2]' (non ci sono '10' , '11') È solo un esempio o una regola generale? – jfs

risposta

23

può essere fatto in O (log N) con una ricerca binaria modificata:

Inizio nel mezzo della matrice: Se array [idx] < IDX il duplicato è a sinistra, altrimenti a destra. Risciacqua e ripeti.

+0

Dovrebbe essere 'array [idx] -array [0]' per la versione generica. – user

5

Ho tentato di elaborare un algoritmo di divisione e conquista per risolvere questo problema, ma non sono sicuro che fosse la risposta giusta.

Certo, si potrebbe fare una ricerca binaria.

Se arr[i/2] >= i/2 il duplicato si trova nella metà superiore dell'array, altrimenti si trova nella metà inferiore.

while (lower != upper) 
    mid = (lower + upper)/2 
    if (arr[mid] >= mid) 
     lower = mid 
    else 
     upper = mid-1 

Poiché la matrice tra lower e upper viene dimezzata ogni iterazione, l'algoritmo viene eseguito in O (log n).

ideone.com demo in Java

+0

[in Python] (http://ideone.com/YHf9i) – jfs

7

Se nessun numero è presente nella matrice, come nell'esempio, è fattibile in O (log n) con una ricerca binaria. Se a[i] < i, il duplicato è precedente a i, altrimenti è dopo i.

Se c'è un numero assente e uno duplicato, sappiamo ancora che se a[i] < i il duplicato deve essere prima i e se a[i] > i, il numero di assenti deve essere prima di i e il duplicato dopo. Tuttavia, se a[i] == i, non sappiamo se il numero mancante e il duplicato sono entrambi precedenti allo i o entrambi dopo i. In questo caso, non vedo un modo per un algoritmo sublineare.

+0

Sono molto in ritardo, ma se permetti numeri mancanti, è davvero impossibile (ammesso che tu non possa leggere un numero arbitrario di celle in O (1)). Supponiamo di prendere in considerazione le voci di dimensione n + 1 (n> = 2) e ci limitiamo a questo sottoinsieme di voci: {[0,0,2, ..., n], [0,1,1,3, ..., n ], ..., [0,1, ..., k, k, k + 2, ..., n], ..., [0,1, ..., n-1, n-1]}. Supponiamo che tu sappia già il contenuto di una qualsiasi delle celle fino a (n-2) e che siano distinti a coppie, ci sono ancora almeno 2 possibilità e non puoi discriminarne nessuna. Pertanto è necessario leggere almeno (n-1) le celle per decidere quale numero è il duplicato. – Caninonos

0

L'array di esempio è leggermente diverso dalla domanda. Poiché n è la lunghezza dell'array e ci sono un solo duplicato nell'array, il valore di ogni elemento dell'array dovrebbe essere in [0, n-1].

Se questo è vero, allora questa domanda è la stessa con How to find a duplicate element in an array of shuffled consecutive integers?

Il seguente codice dovrebbe trovare il duplicato in O (n) e O (1) spazio.

public static int findOnlyDuplicateFromArray(int[] a, boolean startWithZero){ 
    int xor = 0; 
    int offset = 1; 
    for(int i=0; i < a.length; i++){ 
     if(startWithZero) 
      xor = xor^(a[i] + offset)^i; 
     else 
      xor = xor^a[i]^i; 
     } 
     if(startWithZero) 
      xor = xor - offset; 
    return xor; 
} 
+0

Siamo spiacenti, questo non è un tempo meno lineare. Dovrebbe usare la ricerca binaria per raggiungere l'obiettivo. – user1106083

0

Che ne dici? (Ricorsione stile)

public static int DuplicateBinaryFind(int[] arr, int left, int right) 
{ 
    int dup =0; 

    if(left==right) 
    { 
     dup = left; 
    } 
    else 
    { 
     int middle = (left+right)\2; 
     if(arr[middle]<middle) 
     { 
      dup = DuplicateBinaryFind(arr,left, middle-1); 

     } 
     else 
     { 
      dup = DuplicateBinaryFind(arr, middle+1, right); 
     } 
    } 

    return dup; 

} 
1

Differenza tra somma di determinati elementi di matrice e la somma di 0 a n-1 numeri naturali ti dà l'elemento duplicato. La somma di elementi da 0 a n-1 è (N * N-1)/2 esempio di matrice è [0,1,2,3,4,5,6,7,8,8,9] somma di 0 a 9 numeri naturali è: 45 somma di elementi di matrice dati: 53 53-45 = 8 Qual è l'elemento duplicato

+0

sommando tutti gli elementi è O (n) - e quindi oltre il budget – tucuxi