2014-04-26 14 views
5

Dato un numero n, e un array con dimensione m dove m < n. A condizione che ogni numero nell'array sia compreso tra 0 e n-1 (inclusi), voglio ottenere il più efficientemente possibile l'elenco di numeri n-m da 0 a n-1 che non sono nell'array.Genera un elenco di numeri rimanenti

Ecco come lo sto facendo (in pseudocodice), ma ci si sente piuttosto inefficiente e mi chiedo se c'è un modo migliore:

int[] remaining (int[] assigned) { 
    Set<int> s 
    int[n-m] remaining 
    add each int in assigned to s 
    for(i = 0 to n-1) 
     if(not s.contains(i)) remaining.add(i); 
} 

Questo non è un qualsiasi linguaggio di programmazione particolare, ma esso dovrebbe essere ilustrativo Assumiamo che l'accesso a un array sia ovviamente O (1) e l'aggiunta/verifica di un set è O (log (n)) come sarebbe un set AVL. Quindi in pratica sto cercando di ottenere questo in tempo lineare, invece di O (n · logn) come ora, ma se l'array iniziale non è ordinato non so come farlo, o se è possibile anche .

+1

Se si può permettere la memoria, un array di bit di dimensione n può essere utilizzato per risolvere il problema in tempo lineare. (L'algoritmo è ovvio). – ooga

+0

Non seguo assolutamente l'algoritmo ovvio. Potresti spiegare per favore? EDIT: Oh, aspetta, per definizione intendevi booleano? – Setzer22

+0

Oh, mi dispiace! Stavo pensando che avresti impostato l'array di bit su tutti gli 0, passando attraverso l'elenco di numeri impostando il bit corrispondente su 1, quindi passando attraverso l'array di bit e stampando le posizioni di tutti i bit che sono ancora zero. – ooga

risposta

2

penso che sarebbe un po 'più veloce pseudocodice anche

int[] remaining (int[] assigned) { 
    Set<int> s 
    int[n] all 
    int[n-m] remaining 
    for(i = 0 to m-1) 
     all[assigned[i]]=-1 
    int counter=0 
    for(i = 0 to n-1) 
     if (all[i]==-1) 
      remaining[counter]=all[i] 
      counter++ 
    return remaining 
} 
3

copia la matrice in una hashmap H. Questo richiede O(m).

for i from 0 to n-1 
    if(H.ispresent(i) == FALSE) 
     output i 

Questo ciclo prende O(n). Come n>=m la complessità generale è O(n)

+0

O ora che ci penso, posso usare un array di interi (che sarebbe una particolare implementazione di una mappa hash con coppie chiave-valore int-int Comunque, bella risposta, grazie! – Setzer22

+0

@ Setzer22 Sarebbe identico (in sostanza) all'idea del bit array, tranne che l'uso di ints (o di una hashmap) richiederebbe molto più spazio. – ooga

2

Il bitset (bit array) idea:

#include <iostream> 
#include <fstream> 
#include <bitset> 

const int SIZE = 10; // for example 

int main() { 
    std::bitset<SIZE> bs; 
    int i; 

    std::ifstream fin("numbers.txt"); 
    while (fin >> i) 
     bs.set(i); 
    fin.close(); 

    for (i = 0; i < SIZE; ++i) 
     if (!bs[i]) 
      std::cout << i << '\n'; 

    return 0; 
} 
+0

Beh, in realtà sto usando Java quindi non ho fortuna con l'STL, ma stavo chiedendo l'idea generale e questo risponde, quindi grazie !.E nonostante questo sia essenzialmente lo stesso il concetto di bitset porta con sé un brutto sovraccarico dato che la memoria di qualsiasi computer moderno deve essere scritta almeno byte per byte, quindi non c'è accesso magico, sono solo operazioni bituminose al di sotto, che la maggior parte delle persone non mi piace – Setzer22

+0

@ Setzer22 Questo è il compromesso, va bene. Immaginavo che avresti, potenzialmente, milioni (o miliardi) di numeri, altrimenti perché preoccuparti dell'ottimizzazione? Quindi l'uso della memoria sarebbe importante, IMHO. – ooga

1

Se dovete trovare 1 o 2 numeri mancanti, puoi sempre usare la somma e/o il prodotto dei numeri per capire i numeri mancanti. Se è più di 2

Codice per l'utilizzo di un Bitset in java per trovare i numeri mancanti.

public List<Integer> findMissingNumbers(List<Integer> input,int maxNum){ 

/* È inoltre possibile interate l'elenco e trovare il manum più tardi. Il bitset si basa sul vettore e può aumentare di dimensioni */ if (input == null || input.size() == 0) return null;

BitSet existSet=new BitSet(maxNum); 
for(int val:input){ 
    existSet.set(val); 
} 

List<Integer> missingNum=new ArrayList<Integer>(); 
for(int i=0;i<existSet.length()){ 
    nextIndex=bitSet.nextClearBit(); 
    if(nextIndex==-1) 
     break; 
    missingNum.add(nextIndex); 
    index=nextIndex+1; 

} 
return missingNum; 

}

Problemi correlati