2011-01-26 72 views
5

假设我想检查一个数字n = 123是否有重复的数字。我试过:检查号码重复数字的最快方法是什么?

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

有没有更快的解决方案来解决这个问题?

更新
对不起,不清楚。上面的代码是用C++编写的,仅用于描述目的。我必须在TI-89中解决这个问题,其中有9位数字。由于内存和速度的限制,我正在寻找一种最快的方式。

TI-89只有几个条件关键字:

  • 如果
  • 如果...那么
  • 时(
  • 对于... ENDFOR
  • 虽然... ENDWHILE
  • Loop ... EndLoop
  • Custom ... EndCustom

感谢,

+0

由于您的解决方案仅限于三位数字,只需制作具有重复数字的数字的哈希表,并检查数字是否包含在其中。 – aaronasterling 2011-01-26 04:54:48

+0

您还需要处理少于三位的数字(如果这是有效的输入)。现在`n = 1`将被拒绝为重复数字(前导零)。 – Thilo 2011-01-26 05:07:43

+0

您正在使用TI-89上的哪种语言? – 2011-01-26 05:11:15

回答

10

更快,可能没有(但你无论如何都应该衡量,以防万一 - 我的优化口头禅是"measure, don't guess")。但意图更清晰,我认为,是的,并且能够处理任意大小的整数。

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

如果你有机会在有限的范围内,你可以使用时间牺牲空间的由来已久的做法。

说你0和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 
}; 

,只是做的hasDupes[n]查表。


基础上,当你需要处理的九位,一个数十亿元素的数组(上面第二个解决方案)的编辑很可能不会有可能在计算器:-)

我会选择第一个解决方案。

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

类似的东西应该只要n为负,并且int具有至少radix位工作。


digits_mask是一个bitset(位0代表一个0数字的发生,位1表示1位等的发生)。

位图填充了n的最低有效位,其余位数向下移位。如果有更多数字,并且新的最低有效数字被标记为先前已发生,则返回true,否则重复。

当没有更多数字时,返回false。

1 << x返回1,2,4,8等:用于测试/设置比特位的掩码。

a |= za = a | z的简写,它通过a的联合从z来设置比特。

a & zaz中的位的相交,如果没有设置,则为零(假),如果设置了任何值,则为非零(真)。

1

我做了一个速成班在TI-89的基本回答:)

让我们来看看这是否正常工作(我没有一个模拟器,所以无法查询)。

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 
相关问题