检查数字重复数字的最快方法是什么?

时间:2011-01-26 04:50:31

标签: algorithm numbers

假设我想检查数字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只有几个条件关键字:

  • 如果
  • 如果......那么
  • 何时(
  • For ... EndFor
  • 虽然...... EndWhile
  • 循环... EndLoop
  • 自定义... EndCustom

谢谢,

3 个答案:

答案 0 :(得分: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]


根据你需要处理九位数的编辑,你的计算器可能无法实现十亿元素数组(上面的第二个解决方案): - )

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

答案 1 :(得分: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的{​​{1}}的联合设置位。

za & za中的位的交集,如果没有设置则为零(false),如果设置则为非零(true)。< / p>

答案 2 :(得分: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