【问题标题】:What is the fastest way to check for duplicate digits of a number?检查数字重复数字的最快方法是什么?
【发布时间】:2011-01-26 04:50:31
【问题描述】:

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

  • 如果
  • 如果...那么
  • 何时(
  • 为了...结束为了
  • While ... EndWhile
  • 循环...结束循环
  • 自定义...结束自定义

谢谢,

【问题讨论】:

  • 由于您的解决方案仅限于三位数字,因此只需将具有重复数字的数字制作一个哈希表并检查该数字是否包含在其中。
  • 您还需要处理少于三位数的数字(如果这是有效输入)。现在n = 1 将被拒绝,因为它有重复的数字(前导零)。
  • 您在 TI-89 上使用哪种语言?
  • @belisarius:它不是真正的语言。它旨在仅解决数学问题。所以它没有数组。只有forif-elsedowhile 和算术。
  • @Chan 查看关于 TI-89 的语言建议ocf.berkeley.edu/~pad/faq/prog.html

标签: algorithm numbers


【解决方案1】:

不一定更快,但无论如何你都应该测量,以防万一 - 我的优化口号是 "measure, don't guess"

但我相信它的意图更清晰(并且足够简单,可以翻译成更简单的计算器语言。它还能够处理任意大小的整数。

int hasDupes (unsigned int n) {
    // Flag to indicate digit has been used, all zero to start.
    int used[10] = {0};

    // More than 10 digits must have duplicates, return true quickly.
    if (n > 9999999999) return 1;

    // Process each digit in number.
    while (n != 0) {
        // If duplicate, return true as soon as found.
        if (used[n%10]) return 1;

        // Otherwise, mark used, go to next digit.
        used[n%10] = 1;
        n /= 10;
    }

    // No duplicates after checking all digits, return false.
    return 0;
}

如果您的可能性范围有限,您可以使用由来已久的以牺牲空间换时间的方法。例如,假设您谈论的是 0 到 999 之间的数字(: : 标记仅表示我已删除的数据以使答案的大小易于管理):

const int *hasDupes = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  //   0 -   9
        0, 1, 0, 0, 0, 0, 0, 0, 0, 0,  //  10 -  19
        0, 0, 1, 0, 0, 0, 0, 0, 0, 0,  //  20 -  29
                    :  :
        0, 0, 1, 0, 0, 1, 0, 0, 0, 0,  // 520 - 529
                    :  :
        0, 1, 0, 0, 0, 0, 0, 0, 1, 0,  // 810 - 819
                    :  :
        0, 0, 0, 0, 0, 0, 0, 1, 0, 1,  // 970 - 979
        0, 0, 0, 0, 0, 0, 0, 0, 1, 1,  // 980 - 989
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 990 - 999
};

只需对hasDupes[n] 进行表查找。表格本身可以通过编程方式生成(一次),然后插入到您的代码中以供使用。

但是,根据您声明需要处理九位数字的编辑,您的计算器可能无法使用十亿元素数组。因此,我会选择第一个解决方案。

【讨论】:

  • 感谢您的解决方案。但是我只是使用 C++ 来描述这个问题。我必须在 TI-89 中对其进行编程,所以我正在寻找一种更快的方法。
  • @Chan,这个版本的好处是一旦发现重复就提前退出。值得一看。它还具有处理具有任意位数的数字的优点(尽管在这种情况下它是最佳的,只要有十个以上的数字,它就应该返回 false:pidgeons 和孔)
【解决方案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(bit 0代表出现0位,bit 1代表出现1位等)。

位图由n 的最低有效数字填充,其余数字向下移动。如果有更多数字,并且新的最低有效数字被标记为以前出现过,则返回 true,否则重复。

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

1 &lt;&lt; x 返回 1、2、4、8 等:用于测试/设置位集中位的掩码。

a |= za = a | z 的简写,它通过az 的联合来设置位。

a &amp; zaz 中的位的交集,如果未设置则为零 (false),如果设置了则为非零 (true)。

【讨论】:

    【解决方案3】:

    我参加了 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
    

    【讨论】:

    • 我不知道这是否正确,但是使用 TI-basic 的 +1 :p B - C -&gt; B 看起来很可疑。
    • @pst 我同意,但我是通过示例学习的。在此处查看第一块代码示例en.wikipedia.org/wiki/TI-BASIC :)
    • 我的意思是我希望 B / 10 -&gt; B 或类似的数字倾斜。
    • @pst 这需要比我更多的语言算术知识!你怎么知道它会返回一个整数?
    猜你喜欢
    • 2021-04-27
    • 1970-01-01
    • 2015-05-13
    • 2018-05-04
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多