2011-01-26 2 views
5

Diciamo che voglio controllare se un numero n = 123 ha cifre duplicate. Ho provato:Qual è il modo più veloce per verificare le cifre duplicate di un numero?

#include <iostream> 

using namespace std; 

int main() { 
    int n = 123; 
    int d1 = n % 10; 
    int d2 = (n/10) % 10; 
    int d3 = (n/100) % 10; 
    if(d1 != d2 && d1 != d3 && d2 != d3) { 
     cout << n << " does not have duplicate digits.\n"; 
    } 
} 

Esiste una soluzione più rapida a questo problema?

Aggiornamento
Mi dispiace per non essere chiaro. Il codice sopra è stato scritto in C++ solo a scopo descrittivo. Devo risolvere questo problema in TI-89, con un numero di 9 cifre. E dal limite della memoria e della velocità, sto cercando il modo più veloce possibile.

TI-89 ha solo diversi per condizione Parole chiave:

  • Se
  • If ... Then
  • quando (
  • Per ... EndFor
  • Mentre ... EndWhile
  • Loop ... EndLoop
  • Personalizzato ... EndCustom

Grazie,
Chan

+0

Poiché la soluzione è limitata a numeri a tre cifre, è sufficiente creare una tabella hash dei numeri con cifre ripetute e controllare se il numero è contenuto. – aaronasterling

+0

È inoltre necessario gestire i numeri con meno di tre cifre (se questo è un input valido). Al momento 'n = 1' sarà rifiutato come se avesse cifre duplicate (gli zeri iniziali). – Thilo

+0

Su quale lingua della TI-89 state lavorando? –

risposta

10

più veloce, forse non (ma si dovrebbe misurare in ogni caso, nel caso in cui - il mio mantra è l'ottimizzazione "measure, don't guess"). Ma più chiaro nelle intenzioni, penso, sì, e in grado di gestire interi di dimensioni arbitrarie.

int hasDupes (unsigned int n) { 
    // Flag to indicate digit has been used. 

    int i, used[10]; 

    // Must have dupes if more than ten digits. 

    if (n > 9999999999) 
     return 1; 

    // Initialise dupe flags to false. 

    for (i = 0; i < 10; i++) 
     used[i] = 0; 

    // Process all digits in number. 

    while (n != 0) { 
     // Already used? Return true. 

     if (used[n%10]) // you can cache n%10 if compiler not too smart. 
      return 1; 

     // Otherwise, mark used, go to next digit. 

     used[n%10] = 1; // and you would use cached value here. 
     n /= 10; 
    } 

    // No dupes, return false. 

    return 0; 
} 

Se si dispone di una gamma limitata di possibilità, è possibile utilizzare il metodo consacrato di sacrificare spazio per il tempo.

Dire che stai parlando di numeri compresi tra 0 e 999:

const int *hasDupes = { 
// 0 1 2 3 4 5 6 7 8 9 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // x 
    0, 1, 0, 0, 0, 0, 0, 0, 0, 0, // 1x 
    0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 2x 
    : 
    0, 0, 0, 0, 0, 0, 0, 1, 0, 1, // 97x 
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, // 98x 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 99x 
}; 

e solo fare una tabella di ricerca di hasDupes[n].


base alla tua modifica quando si ha bisogno per gestire nove cifre, un array di miliardi di elemento (seconda soluzione sopra) non è destinata probabilmente ad essere possibile sulla calcolatrice :-)

opterei per la prima soluzione.

+0

Grazie per la soluzione. Comunque uso solo C++ per descrivere il problema. Devo programmarlo in TI-89, quindi sto cercando un modo più veloce. – Chan

+0

@Chan, questa versione ha il vantaggio di uscire presto non appena viene trovato un duplicato. Vale la pena profilare per vedere. Ha anche il vantaggio di lavorare per numeri con qualsiasi quantità di cifre (anche se per essere ottimale in quel caso, dovrebbe appena restituire falso non appena ci sono più di dieci cifre: pidgeon e buchi) – aaronasterling

2
template<class T, int radix = 10> 
bool has_duplicate_digits(T n) { 
    int digits_mask = 0; 
    while (digits_mask |= (1 << (n % radix)), n /= radix) 
     if (digits_mask & (1 << (n % radix))) 
      return true; 
    return false; 
} 

Qualcosa del genere dovrebbe funzionare finché n è non negativo e int ha almeno radix bit.


digits_mask è un bitset (bit 0 rappresenta il verificarsi di una cifra 0, bit 1 rappresenta il verificarsi di un 1 cifra, ecc).

La bitmap viene popolata con la cifra meno significativa di n e il resto delle cifre viene spostato verso il basso.Se ci sono più cifre e la nuova cifra meno significativa è contrassegnata come essersi verificata in precedenza, restituire true, altrimenti ripetere.

Quando non ci sono più cifre, restituire false.

1 << x restituisce 1, 2, 4, 8, ecc .: maschere da utilizzare per testare/impostare bit nel set di bit.

a |= z è lo stenoscopio per a = a | z, che imposta i bit dall'unione di a da z.

a & z è l'intersezione dei bit a e z, ed è zero (falso) se non sono impostati e diverso da zero (true) se qualsiasi sono impostati.

1

Ho fatto un corso accelerato di TI-89 di base per rispondere :)

Vediamo se questo funziona (non ho un emulatore, quindi non può controllare).

Test() 
Prgm 
{0,0,0,0,0,0,0,0,0,0}->A 
Title "Request" 
Request "Enter a number",B 
EndDlog 
Expr(B)->B 
While B > 1 
MOD(10,B)->C 
if A[C+1] = 1 goto K 
1->A[C+1] 
B-C->B 
EndWhile 
Title "Done" 
Text "Numbers non repeating" 
Enddlog 
goto J 

Lbl K 
Title "Done" 
Text "Numbers repeating" 
Enddlog 

Lbl J 
EndPrgm 
+0

Non ho idea se questo è corretto, ma +1 per l'uso di TI-basic: p 'B - C -> B' sembra comunque pescoso. –

+0

@ pst Sono d'accordo, ma ho imparato dall'esempio. Vedi il primo blocco di esempi di codice qui http://en.wikipedia.org/wiki/TI-BASIC :) –

+0

Voglio dire che mi sarei aspettato 'B/10 -> B' o simile per il digrignamento delle cifre. –