2014-04-26 19 views
5

Gegeben eine Zahl n und ein Array mit der Größe m wobei m < n. Vorausgesetzt, dass jede Zahl im Array zwischen 0 und n-1 (inklusive) liegt, möchte ich so effizient wie möglich die Liste der n-m Zahlen von 0 bis n-1 erhalten, die nicht im Array sind.Liste der verbleibenden Nummern generieren

Das ist, wie ich es tue (in Pseudo-Code), aber es fühlt sich eher ineffizient und ich frage mich, ob es einen besseren Weg:

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); 
} 

Dies ist keine bestimmte Sprache Computer, aber es sollte sei illusorisch. Wir gehen davon aus, dass der Zugriff auf ein Array natürlich O (1) ist und das Hinzufügen/Überprüfen eines Satzes ist O (log (n)), wie es ein AVL-Satz wäre. Ich versuche also, dies in linearer Zeit zu erreichen, anstatt in O (n · logn), wie es jetzt ist, aber wenn das ursprüngliche Array nicht sortiert ist, weiß ich nicht, wie ich es anstellen soll oder ob es überhaupt möglich ist .

+1

Wenn Sie den Speicher leisten können, könnte eine Reihe von Bits der Größe n verwendet werden, um das Problem in linearer Zeit zu lösen. (Der Algorithmus ist offensichtlich.) – ooga

+0

Ich folge nicht ganz dem, was der offensichtliche Algorithmus ist. Könnten Sie bitte erklären? EDIT: Oh, warte mal, du meinst Boolean? – Setzer22

+0

Oh, Entschuldigung! Ich dachte, dass Sie das Bit-Array auf alle Nullen initiieren würden, gehen Sie durch Ihre Liste von Zahlen, setzen Sie das entsprechende Bit auf 1, und gehen Sie dann durch das Bit-Array und die Positionen aller Bits, die immer noch Null sind. – ooga

Antwort

2

ich denke, es wäre auch

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

Kopieren Sie das Array in eine hashmap H. Dies dauert O(m).

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

Diese For-Schleife dauert O(n). Wie n>=m die Gesamtkomplexität ist O(n)

+0

Oder jetzt, wo ich darüber nachdenke, kann ich ein Array von Ganzzahlen verwenden (was eine spezielle Implementierung einer Hash-Map mit Schlüssel-Wert-Paaren wäre. Int-int. Wie auch immer, nette Antwort, danke! – Setzer22

+0

@ Setzer22 Das wäre identisch (Im Wesentlichen) zu der Bit-Array-Idee, außer dass die Verwendung von Ints (oder einer Hash-Map) wesentlich mehr Platz benötigt – ooga

2

Die bitset (Bit-Array) Idee:

#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

Nun, ich benutze tatsächlich Java, also kein Glück mit der STL, aber ich fragte nach der allgemeinen Idee und dies antwortet es, also danke!Und obwohl dies im Wesentlichen das Gleiche ist, trägt das Bitset-Konzept einen hässlichen Overhead mit sich, da die Speicher jedes modernen Computers mindestens Byte pro Byte geschrieben werden müssen, so dass es keinen magischen Bit-Zugriff gibt, sondern nur bitweise Operationen darunter mag nicht. – Setzer22

+0

@ Setzer22 Das ist der Kompromiss, in Ordnung. Ich nahm an, dass Sie möglicherweise Millionen (oder Milliarden) von Zahlen haben würden. Warum sollten Sie sich dann mit der Optimierung beschäftigen? Also Speicherverbrauch wäre wichtig, IMHO. – ooga

1

Wenn Sie müssen ein wenig schneller Pseudo-Code sein finden 1 oder 2 fehlende Zahlen, können Sie immer die Summe und/oder das Produkt der Zahlen verwenden, um die fehlenden Zahlen herauszufinden. Wenn es mehr als 2

ist

Code für die Verwendung eines Bitsets in Java, um die fehlenden Zahlen zu finden.

/* Sie können auch durch die Liste interagieren und später das MANUM finden. Das Bitset basiert auf Vektor und kann größer werden */ 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; 

}

Verwandte Themen