Hallo zusammen, ich stehe gerade ein bisschen auf dem Schlauch. Ich möchte gerne 10 integer Variablen auf Ungleichheit überprüfen und mir fällt gerade nicht ein wie ich das am besten lösen könnte ohne jede Bedingung händisch abzuklopfen. Hat jemand von euch vielleicht eine Idee. Vielen lieben Dank schon mal.
agneu schrieb: > Ich möchte gerne 10 integer Variablen auf Ungleichheit überprüfen und mir > fällt gerade nicht ein wie ich das am besten lösen könnte ohne jede > Bedingung händisch abzuklopfen. Wenn du sie unbedingt als Einzelvariablen deklarieren musst, wird dir nichts anderes übrig bleiben.
Abhängig von der Art und Weise wie die deklariert sind könntest Du auch auf die erste Variable einen Zeiger machen und den dann weiter zählen... das wäre aber die C-Variante. Willst Du echtes C++ machen, so definierst Du die Integer als Klassen und machst einen Iterator und kannst damit das Problem sicherlich schon in 200-500 Zeilen lösen. Ich persönlich finde es problematisch wenn man C++ als Lehrsprache verwendet.
1 | // ungetestet
|
2 | #include <stddef.h> |
3 | #include <stdbool.h> |
4 | #include <stdio.h> |
5 | |
6 | int main(){ |
7 | int nums[] = {1,2,3,4,5,6,7,8,9,0}; |
8 | size_t num_count = sizeof(nums)/sizeof(*nums); |
9 | size_t i,j; |
10 | bool unique=true; |
11 | for( i=0; i < num_count; i++ ) |
12 | for( j=i+1; j < num_count; j++ ) |
13 | if( nums[j] == nums[i] ){ |
14 | unique = false; |
15 | break; |
16 | }
|
17 | if( unique ){ |
18 | printf("every number is unique\n"); |
19 | }else{ |
20 | printf("not every number is unique\n"); |
21 | }
|
22 | return 0; |
23 | }
|
Das kommt drauf an, wo die Variablen liegen. Wenn sie in einem Standard-Container wie std::vector untergebracht sind, kannst Du einfach die beiden Container mit "==" vergleichen. Wenn Du nur den Teil eines Containters oder auch C-Arrays vergleichen willst, kannst Du std::equal benutzen. Oder Du schreibst eben selber eine Schleife ...
Wenn bei Daniels Beispiel die innere Schleife abgebrochen wird (wenn "unique" auf false gesetzt wird), ist es sinnlos, die äußere Schleife weiterlaufen zu lassen. Also sollte eine Überprüfung von "unique" in die Schleifenabbruchbedingung (i < num_count) einfließen.
agneu schrieb: > Hat jemand von euch vielleicht eine Idee. Einfachster Algorithmus wäre, du gehst mit jedem Wert durch die ganze Liste. Das kann man optimieren, in dem man nur noch die Elemente hinter dem betrachteten Element durchsucht, da ein Duplikat vor dem betrachtetem Element, vorher schon aufgefallen wäre:
1 | #include <algorithm> |
2 | #include <initializer_list> |
3 | #include <cassert> |
4 | |
5 | template < class Iter > |
6 | bool contains_duplicates( Iter begin, Iter end ) |
7 | { |
8 | if ( begin == end ) |
9 | return false; |
10 | |
11 | for ( ; begin != end; ) |
12 | { |
13 | const auto value = *begin; |
14 | ++begin; |
15 | |
16 | if ( std::find( begin, end, value ) != end ) |
17 | return true; |
18 | } |
19 | |
20 | return false; |
21 | } |
22 | |
23 | template < class T > |
24 | bool contains_duplicates( const std::initializer_list< T >& values ) |
25 | { |
26 | return contains_duplicates( values.begin(), values.end() ); |
27 | } |
28 | |
29 | int main() |
30 | { |
31 | assert( !contains_duplicates( std::initializer_list< int >{} ) ); |
32 | assert( !contains_duplicates( { 2 } ) ); |
33 | assert( !contains_duplicates( { 2, 3, 1 } ) ); |
34 | assert( contains_duplicates( { 2, 2, 0 } ) ); |
35 | assert( contains_duplicates( { 2, 0, 2 } ) ); |
36 | |
37 | const int i1 = 1, i2 = 2, i3 = 3, i4 = 4, i5 = 5, i6 = 6, i7 = 7; |
38 | |
39 | assert( !contains_duplicates( { i1, i2, i3, i4, i5, i6, i7 } ) ); |
40 | } |
Der Algorithmus hat eine Komplexität von O(n^2). Wenn es sehr viel mehr Elemente sind, als 10 dann könnte man die Elemente auch vorher sortieren (O(log n) und dann einmal durch gehen und die Nachbarn betrachten (n*O(log n)) mfg Torsten
Warum so C-Style wenns hier ausdrücklich um C++ geht? Wie wärs mit std::sort+std::unique, oder std::set, oder std::map (mißbräuchliche Nutzung), jeweils zusammen mit size()? HTH
Torsten R. schrieb: > if ( begin == end ) > return false; Das ist überflüssig, da es schon der Schleifenbedingung weiter unten entspricht.
Torsten R. schrieb: > als 10 dann könnte man die Elemente auch vorher sortieren > (O(log n) und In O(log n) sortieren? Not bad!
apr schrieb: > Torsten R. schrieb: >> als 10 dann könnte man die Elemente auch vorher sortieren >> (O(log n) und > > In O(log n) sortieren? Not bad! Oder so ähnlich ;-) Auf jeden Fall deutlich besser als n^2. Danke für den Hinweis.
std::unordered_set items = {1, 2, 3, 4, 3, 4, 6}?
g457 schrieb: > std::sort+std::unique Für std::unique muss der Container nicht sortiert sein. Eine Möglichkeit wäre auch noch std::sort + std::adjacent_find. Ohne zu wissen, wie und wo die Variablen gespeichert sind, schlage ich vor, die Variablen in ein std::set zu packen und nach jeden Einfügen zu prüfen, ob der Wert eingefügt wurde oder nicht (via Rückgabewert von std::set::insert). Wurde er nicht eingefügt, ist er bereits vorhanden.
>> std::sort+std::unique > > Für std::unique muss der Container nicht sortiert sein. Da behauptet die Doku [0] was anderes, zumindest für die hiesigen Zwecke:
1 | Removes all consecutive duplicate elements from the range [..] |
2 | ^^^^^^^^^^^ |
Nix für ungut. [0] http://en.cppreference.com/w/cpp/algorithm/unique
g457 schrieb: > Da behauptet die Doku [0] was anderes, zumindest für die hiesigen > Zwecke: > Removes all consecutive duplicate elements from the range [..] > ^^^^^^^^^^^ Oh, das Wort hab ich überlesen. Danke für die Korrektur. g457 schrieb: > Nix für ungut. Kein Problem.
g457 schrieb: >>> std::sort+std::unique >> >> Für std::unique muss der Container nicht sortiert sein. Du denkst die Standardbibliothek macht, was du erwartest? Haha, guter Witz :D
Wenn std::minmax_element nicht völlig blöd gebaut ist, sollte das O(n) sein. Geht natürlich nur bei mit < vergleichbaren Datentypen.
1 | #include <algorithm> |
2 | #include <iostream> |
3 | #include <vector> |
4 | |
5 | int main() |
6 | {
|
7 | std::vector<int> A{1,1,2,1,1}; |
8 | std::vector<int> B{1,1,1,1,1}; |
9 | |
10 | auto mima = std::minmax_element(A.begin(), A.end()); |
11 | bool all_equal = (*mima.first == *mima.second); |
12 | |
13 | auto mima2 = std::minmax_element(B.begin(), B.end()); |
14 | bool all_equal2 = (*mima2.first == *mima2.second); |
15 | |
16 | |
17 | std::cout << "A: " << all_equal << "\tB: " << all_equal2 << "\n"; |
18 | |
19 | |
20 | }
|
Argh, es sollen alle ungleich sein. Problem nicht verstanden, setzen, 5-.
Hashtabelle: Einfügen, Suchen: O(1) (amortisiert) Solange einfügen bis ein Element doppelt vorkommt. Laufzeit O(n), Worstcase O(n²) in Abhängigkeit vom Wertebereich der Integer, der Anzahl der Werte und der Implementation. Ob das bei nur 10 Integern schneller ist, ist allerdings nicht sicher...
:
Bearbeitet durch User
Mir fiele noch ein rekursiver Ansatz ein, d.h. eine Funktion, die das erste Element einer Liste gegen den Rest der Liste vergleicht und sich dann selbst mit dem Rest der Liste aufruft. Effizienz ist aber etwas anderes.
std::sort in Kombination mit std::adjacent_find wäre auch noch möglich.
1 | std::vector<int> v{0, 1, 2, 3, 40, 40, 41, 41, 5}; |
2 | auto it = std::adjacent_find(v.begin(), v.end()); |
3 | if (it == v.end()) |
4 | // no equal elements found
|
Wenn die Liste sortiert ist braucht Du logischerweise einfach nur gucken ob hintereinanderliegende Elemente gleich sind. Die Frage ist halt jetzt ob Du irgendeinen Mehrwert woanders erhältst wenn Du die Elemente sortierst, bzw ob es möglich ist sie vielleicht schon beim Anlegen sortiert anzulegen, und ob das für Dein Problem nützlich ist. Das weißt wohl nur Du selbst.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.