2011-01-26 26 views
5

Powiedzmy, że chcę sprawdzić, czy liczba n = 123 ma zduplikowane cyfry. Próbowałem:Jaki jest najszybszy sposób sprawdzenia duplikatów cyfr numeru?

#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"; 
    } 
} 

Czy istnieje szybsze rozwiązanie tego problemu?

Aktualizacja
Przepraszam za to, że niejasne. Powyższy kod został napisany w C++ tylko w celach opisowych. Muszę rozwiązać ten problem w TI-89, z liczbą 9 cyfr. A ponieważ ograniczam pamięć i szybkość, szukam najszybszego możliwego sposobu.

TI-89 ma tylko warunek kilka słów kluczowych:

  • Jeśli
  • If ... Then
  • kiedy (
  • Dla ... EndFor
  • Chociaż ... ENDWHILE
  • Pętla ... EndLoop
  • Niestandardowe ... EndCustom

Dzięki
Chan

+0

Ponieważ rozwiązanie jest ograniczona do trzech liczb dwucyfrowych, po prostu zrobić stolik hash z numerów, które mają powtarzające się cyfry i sprawdzić, czy numer jest w niej zawarte. – aaronasterling

+0

Należy również obsługiwać liczby zawierające mniej niż trzy cyfry (jeśli są to prawidłowe dane wejściowe). W tej chwili 'n = 1' zostanie odrzucone jako posiadające zduplikowane cyfry (początkowe zera). – Thilo

+0

W jakim języku w TI-89 pracujesz? –

Odpowiedz

10

Szybciej, ewentualnie nie (ale należy mierzyć tak, na wszelki wypadek - mój optymalizacja mantra jest "measure, don't guess"). Ale jaśniej w zamierzeniu, myślę, że tak, i jestem w stanie obsłużyć dowolne wielkości całkowite.

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

Jeśli masz ograniczony zakres możliwości, można stosować metodę uświęcone poświęcania miejsca na czasie.

Załóżmy, że mówimy o numerach od 0 do 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 
}; 

i po prostu zrobić odnośnika stołową hasDupes[n].


oparciu o edycję kiedy trzeba obsłużyć dziewięć cyfr tablicy miliardów elementu (drugie rozwiązanie wyżej) nie jest zapewne będzie to możliwe na kalkulatorze :-)

wybrałbym pierwsze rozwiązanie.

+0

Dzięki za rozwiązanie. Jednak po prostu używam C++ do opisania problemu. Muszę go zaprogramować w TI-89, więc szukam szybszego sposobu. – Chan

+0

@Chan, wersja ta ma tę zaletę, wychodząc wcześnie, jak tylko zostanie znaleziony duplikat. Warto zobaczyć profilowanie. Ma również tę zaletę, że działa na liczbach z dowolną liczbą cyfr (chociaż dla tego jest optymalna, powinna zwracać fałsz, gdy pojawi się więcej niż dziesięć cyfr: pidgeons i dziury) – 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; 
} 

Coś takiego powinno działać tak długo, jak n jest nieujemna i int ma co najmniej radix bitów.


digits_mask jest bitset (bit 0 reprezentuje wystąpienie cyfrę 0, 1 bit reprezentuje wystąpienie 1 cyfry itp).

Bitmapa jest wypełniona najmniej znaczącą cyfrą n, a pozostałe cyfry są przesunięte w dół.Jeśli jest więcej cyfr, a nowa najmniej znacząca cyfra jest oznaczona jako wcześniejsza, zwróć true, w przeciwnym razie powtórz.

Gdy nie ma więcej cyfr, return false.

1 << x zwraca 1, 2, 4, 8, itp .: maski użyć do testów/zestaw bitów w bitset.

a |= z jest skrótem dla a = a | z, który ustawia bity według związku a z z.

a & z jest przecięcie bitów a i z, a wynosi zero (fałsz), jeśli nie jest ustawiona i niezerowe (prawda), jeśli są ustawione.

1

Zrobiłem kurs w TI-89 Podstawowy odpowiedzieć :)

Zobaczymy, czy to zadziała (nie mam emulatora, więc nie mogę sprawdzić).

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

Nie mam pojęcia, czy to jest poprawne, ale +1 dla użycia TI-basic: p 'B - C -> B' wygląda jednak podejrzanie. –

+0

@pst Zgadzam się, ale nauczyłem się przez przykład. Zobacz pierwszy blok przykładów kodu tutaj http://en.wikipedia.org/wiki/TI-BASIC :) –

+0

Chodzi mi o to, że oczekiwałem "B/10 -> B" lub podobnego do cyfry. –

Powiązane problemy