【问题标题】:How do I extract missing digits from an integer?如何从整数中提取缺失的数字?
【发布时间】:2017-01-24 16:23:38
【问题描述】:

我正在尝试获得以下输出:

Enter integer: 87240

Missing digits: 1 3 5 6 9

到目前为止,这是我的代码:

// Extract numbers inside integer n

while (numOfDigits > 0)
{    
    int digit = n % 10;

    int missing = 0;

    while ((digit != missing) && (missing < 10))
    {
        cout << missing << " ";
        missing++;
    }

    numOfDigits--;
    n /= 10;
}

打印出来

Enter integer: 87240

Missing digits: 0 1 2 3 0 1 0 1 2 3 4 5 6 0 1 2 3 4 5 6 7

有什么方法可以在不使用数组的情况下做到这一点?

【问题讨论】:

  • 就我个人而言,我只是将数字作为字符串输入,然后使用find() 检查每个数字是否存在。
  • “不使用数组”是什么意思?你的代码在哪里使用数组?
  • 我认为他的意思是不使用数组(正如他尝试做的那样)来做到这一点,这通常是需要的(例如过滤掉使用过的数字)。尽管如此,数组(10 项)所需的大小并不是很大,所以我可能会使用数组来允许 O(n) 运行时间而不是 O(n^2)。

标签: c++ syntax while-loop extract digits


【解决方案1】:

这是一个使用单个整数 (acc) 来记住已看到的数字的实现:

#include <iostream>

using uuint = unsigned long long int;

uuint p(uuint n) { ++n; return n * n - n + 41; }

void print_missing(uuint n)
{
    std::cout << "Number " << n << " is missing the following digits:";
    uuint acc = 1;
    while (n)
    {
        uuint q = p(n % 10);
        if (acc % q != 0) acc *= q;
        n /= 10;
    }
    for (int i = 0; i != 10; ++i)
    {
        if (acc % p(i) != 0) std::cout << " " << i;
    }
    std::cout << "\n";
}

int main()
{
    for (uuint n; std::cin >> n; )
        print_missing(n);
}

【讨论】:

  • 是的,通过使用位数组(一个数字)而不是常规的 10 项数组来“作弊”。顺便提一句。只需要 10 位来存储信息就足够了(使用位移位和位操作时),所以 unsigned short(至少 2B)应该足以累积结果;)
  • @axalis:我想这甚至会让人谈论作弊问题! :-)
  • 我想评论一下,我赞成这个不是因为它是一个好的解决方案,而是因为它满足了一个坏问题的要求。
  • @JonathanMee:您的位置已被记录。没有人会接受你的投票作为对我代码的认可:-)
【解决方案2】:

您可以使用for 循环,不需要数组:

#include <string>
#include <iostream>
#include <cstdlib>

int main()
{
  std::string integer;
  std::cout << "Enter integer: ";
  std::getline(std::cin, integer);
  for (unsigned int i = 0; i < 10; ++i)
  {
    const char c = '0' + i;
    if (integer.find(c) == std::string::npos)
    {
      cout << i << " ";
    }
  }
  return EXIT_SUCCESS;
}

以上版本将数字保留为文本形式,更易于搜索数字。
您可以使用嵌套循环来检查数字的每个数字。

【讨论】:

  • 然而公平地注意到std::string 确实是一个数组,所以它不符合“不使用数组”的要求。并且可能会比“常规数组”版本慢,因为这需要遍历字符串(并比较数字)10 次而不是一次。
【解决方案3】:

您是否有兴趣使用string 而不是数组?这些或多或少相同的想法,但给定输入string n,我们可以找到任何未使用的数字,如下所示:

const auto digits = "0123456789"s;

sort(begin(n), end(n));
set_difference(cbegin(n), cend(n), cbegin(digits), cend(digits), ostream_iterator<char>(cout, " "));

Live Example

【讨论】:

  • 我不知道set_difference,自己写了不止一次。谢谢!
  • @YSC 和你一样,我通过看到这里的人们使用它们来学习我的大部分标准算法。但是,如果您打算不仅仅是一名普通的 C++ 程序员,那么阅读此列表可能不会有什么坏处:en.cppreference.com/w/cpp/algorithm
  • 我喜欢&lt;algorithm&gt; 和一般的函数式编程;但他们被太多人认为太复杂了。由于可读性比我个人的享受更重要,我使用命令式风格。生活如此悲惨……
  • @YSC 哇...这听起来很讽刺,因为网上的一切都在讽刺,但说真的,这就像我整个星期听到的最悲伤的事情:(
【解决方案4】:

这里的版本使用单个整数来累积结果(技术上仍然是位数组):

#include <iostream>
#include <cmath>

void check(int n)
{
    unsigned short bits = 0;
    while (n) {
        bits |= 1 << std::abs(n % 10);
        n /= 10;
    }
    std::cout << "Missing digits:";
    for (unsigned i = 0; i != 10; ++i) {
        if (((bits >> i) & 1) == 0)
            std::cout << " " << i;
    }
    std::cout << std::endl;
}

int main()
{
    int n;
    std::cout << "Enter a number: ";
    std::cin >> n;
    check(n);
    return 0;
}

【讨论】:

  • 我想评论一下,我赞成这个不是因为它是一个好的解决方案,而是因为它满足了一个坏问题的要求。
【解决方案5】:

这个没有数组。

#include <stdio.h>

int NumHasDigit(int num, int digit)
{
    while (num)
    {
        if (num%10 == digit) 
        {
            return 1;
        }
        num /= 10;
    }   
    return 0;
}

int main(void) {
    int x;

    printf("Enter int: ");
    scanf("%d\n", &x);

    printf("Missing Digits:\n");
    for(int i=0; i<10; ++i)
    {
        if (!NumHasDigit(x,i)) printf("%d ", i);
    }

    return 0;
}

示例输入:
34567

样本输出:
Missing Digits
0 1 2 8 9

【讨论】:

  • 我的理解是digits是一个数组,OP说不使用数组。
  • 返回int而不是bool的任何特殊原因?
  • 因为我是一个老派的 C 程序员……在bool 存在之前。你想换吗?那是你的工作。
猜你喜欢
  • 2020-07-06
  • 2017-07-07
  • 2019-02-01
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多