【问题标题】:C: Finding closest number to the first without repeating digits from the second number?C:找到最接近第一个数字而不重复第二个数字的数字?
【发布时间】:2014-12-23 18:06:26
【问题描述】:

我读了两个号码,都是int

我需要做的是打印高于但最接近第一个数字的数字,例如378,但包含第二个数字中的任何数字,例如,78

输入:378 78,输出:390,因为这是378 之上的最小数字,不包含78 的任何数字。

输入:3454 54,输出:3600,因为3600 是第一个不包含54 的最接近的数字,54 的数字。

我试图通过从第二个数字的长度获取第一个数字的最新模数来做到这一点。例如:

378 78

378 mod 100 == 78,然后比较7878 的数字,如果有相同的数字移动到379,然后检查379 mod 100 == 79。比较7978时,7是同一个数字。

以此类推,直到我们得到390。这应该适用于所有 N 大小的数字。

这是我到目前为止所做的……几乎什么都没有。

#include <stdio.h>

int main()
{
    int number1, number2;
    int closest = number1 + 1;
    scanf("%d %d",&number1,&number2);
    
    int count_modulus = 1;
    
    while(number2)
    {
        count_modulus = count_modulus * 10;
        number2 = number2 / 10;
    }
    int mod = count_modulus;
    int n2 = number2;
    while(number1)
    {
        int remain = number1 % mod;
        while(remain)
        {
            if((remain % 10 == number2 % 10))
            {
                
            }
            else
            {
                
            }
        }
    }
    printf("%d",closest);
    return 0;
}

【问题讨论】:

  • int closest = number1 + 1; 这里 number1 未初始化。
  • 没关系,因为如果我有 378 和 78,它需要从 379 开始。
  • 检查您的代码。你在拥有价值之前正在做+1
  • 没关系,我只需要第二个while括号里的代码,最接近的是加一,因为我需要检查下一个数字,并在while操作。跨度>
  • 看来您的方法只考虑大于number1 的数字。如果您想找到“最接近的”,为什么不考虑小于number1 的数字? 370 70 --> 369

标签: c closest digit


【解决方案1】:

我不完全相信你的模方法会起作用,因为如果你以782378开头,那么7823 mod 100会给你23,它有没有个数字与78 相同,即使7823 有。

但是,即使我误解了规范并且它确实有效,我认为还有更好的方法。首先,如何评分一个数字根据它包含的数字。

如果您的整数至少有 10 位(而且它们会,因为标准要求一个需要 16 位的范围),您可以只使用位掩码,每个位表示数字是否包含数字。我们可以为此使用普通的int,因为十位将使我们无处接近可能导致我们问题的符号位。

打分的代码是:

// Return a bitmask with the bottom ten bits populated,
//   based on whether the input number has a given digit.
// So, 64096 as input will give you the binary value
//     000000 0000111010
//   <-unused ^  ^ ^   ^
//            9876543210 (digits)

int getMask (int val) {
    int mask = 0;                        // All start at 0
    while (val > 0) {                    // While more digits
        mask = mask | (1 << (val % 10)); // Set bit of digit
        val = val / 10;                  // Move to next digit
    }
    return mask;
}

其中的“棘手”部分是声明:

mask = mask | (1 << (val % 10));

它的作用是获取数字的最后一位,val % 10 为您提供将 val 除以 10 的余数。所以123 % 103314159 % 109等等。

下一步是将二进制1 向左移动那么多位,即1 &lt;&lt; (val % 10)。将 1 位向左移动 4 位将为您提供二进制值 10000,因此这只是一种将 1 位置于正确位置的方法。

最后,您将掩码与该计算值进行按位或运算,有效地设置掩码中的等效位,请记住,如果 其中一个或两个位,a | b 位会给您1 ab1

或者您可以查看我的其他答案之一here 了解更多详情。

所以,我听到你问,该位掩码如何帮助我们找到没有共同数字的数字。好吧,AND 位运算符 &amp; 出现的地方 - 如果 两个 输入位都是 1,这只会给你一个 1 位(再次,请参阅前面提供的链接以获取更多详细信息位运算符)。

一旦您有了两个数字的位掩码,您就可以按照以下示例使用&amp;,其中没有通用数字:

Number  Bitmask
               9876543210
------  ----------------
314159  000000 1000111010
   720  000000 0010000101
        ----------------- AND(&)
        000000 0000000000

您可以看到,除非位位置对于 两个 数字都有 1,否则结果位将是 0。如果有任何数字是共同的,那将是一些非零值:

Number  Bitmask      v
               9876543210
------  -----------------
314159  000000 1000111010
   320  000000 0000001101
        ----------------- AND(&)
        000000 0000001000
                     ^
                     The bit representing the common digit 3.

这将我们引向实际的检查代码,在评分函数之上构建相对容易的代码:

#include <stdio.h>

int main (int argc, char *argv[]) {
    // Default input numbers to both zero, then try
    //   to get them from arguments.

    int check = 0, exclude = 0, excludeMask;
    if (argc > 1)
        check = atoi(argv[1]);
    if (argc > 2)
        exclude = atoi(argv[2]);

    // Get the mask for the exclusion number, only done once.

    excludeMask = getMask (exclude);

    // Then we loop, looking for a mask that has no
    //   common bits.

    printf ("%d -> ", check);
    //check++;
    while ((excludeMask & getMask (check)) != 0)
        check++;
    printf ("%d\n", check);

    return 0;
}

流程基本上是从参数中获取数字,计算排除数字的位掩码(结果中包含您想要的数字的位掩码),然后开始查找从支票号码开始,直到找到一张。

我已将最初的 check++ 注释掉,因为我不确定您是否真的想要一个高于的数字,或者是否需要 123 并排除 98应该给你123 的实际起始编号。如果没有,只需取消注释该行。

你已经有了它,如下面的成绩单所示,其中包括你的测试数据:

$ ./myprog 378 78
378 -> 390

$ ./myprog 3454 54
3454 -> 3600

$ ./myprog 123 98  # would give 124 if 'count++' uncommented
123 -> 123

$ ./myprog 314159 6413
314159 -> 500000

它确实有一个潜在的致命缺陷,但如果您在开始查找之前检查排除位掩码,则很容易修复。我将把它作为练习留给读者,但请考虑一下使用以下命令可能会发生什么:

$ ./myprog 1 154862397

当然,如果您想采用其他方式(较小的数字),只需递减 check 而不是递增它。如果你变得消极,你可能还需要更聪明地了解你想要发生的事情,例如:

$ ./myprog 1 102

目前的代码可能无法很好地处理这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    相关资源
    最近更新 更多