问题 数字增加数测试


对于1到9之间的某个数字n,如果它等于n + nn + nnn + ...,则数字称为数字增加。例如,24是数字增加,因为它等于2 + 22(此处n = 2)。

实际上,我的一个朋友问我这个问题,我一直在考虑这个问题,但到目前为止找不到确切的解决方案。有人可以帮忙吗?我需要的函数如果是数字增加则返回true,否则返回false。


4978
2017-10-30 07:15


起源

如果您不需要特定语言的答案,我会回答。 - John Dvorak
我只想要逻辑。任何语言的代码都可以。 - nebula
您只需要9个选项即可试用。它是 (1+11+...) 要么 (2+22+...)... 要么 (9+99+...)。 - Vikas
然后标记[算法] - John Dvorak
你可以使用modulo / division方法进行数字分离。比如,24/10 = 2然后将它乘以10得到20.然后将'2'加到'20'你得到'22'。现在尝试再次将'22'添加到商,然后你得到24.如果它等于给定的数,则它是数字增加。只需将其概括为N位数即可。这很简单。 - SRJ


答案:


我这样做了。退房一次。

int sum = 0, count =0;
bool flag = false;

public bool isDigitIncreasing(int input_number)
{
int  n= get_number_of_digit(input_number); // Gets number of digits
int sum = 0;
    for(int i=0;i<n;i++)
    {
        sum = sum*10+1;
        count = count + sum;
    }

    for(int i=1; i<=9;i++)
    {
        if((input_number)==count*i)
        {
            flag = true;
            break;
        }
        else
        flag = false;
    }
    return flag;

}

    public int get_number_of_digit(int num)
    {

        int size = 0;
        do
        {
            num = num/10;
            size++;
        }while(num>0);
        return size;
    }

0
2017-10-30 09:51



不必要的复杂。 - Amete Blessed


此属性只有相对较少的数字:在范围内 unsigned long long (64位),只有172位数字增加。

因此,就实际解决方案而言,它是有意义的 预先计算它们 并将它们放入哈希。这是Python代码:

# Auxiliary function that generates
# one of the 'nnnn' elements
def digits(digit,times):
  result = 0
  for i in range(times):
    result += digit*(10**i)
  return result

# Pre-computing a hash of digit-increasing
# numbers:
IncDig = {}
for i in range(1,30):
  for j in range(1,10):
    number = reduce(lambda x,y:x+y,[digits(j,k) for k in range(1,i+1)])
    IncDig[number] = None

然后实际的检查功能只是哈希中的查找:

def IncDigCheck(number):
  return (number in IncDig)

这实际上是O(1),并且预计算所花费的时间和空间是最小的,因为只有9个不同的数字(零不计数),因此只有 K*9 类型的组合 n + nn + ... 总和的长度 K


4
2017-10-30 12:33



当n被限制为某个常数时,每个O(n)算法都是O(1)。 - Saeed Amiri
@SaeedAmiri那不是重点。关键是哈希中的查找不依赖于您查找的数字的大小,甚至不依赖于条目的数量。 (后者并不完全正确,取决于哈希如何处理冲突。这就是我说的原因 实质上 O(1)。) - jogojapan
在Python中,对于整数, hash(x) == x因此很容易发生一些碰撞真的很糟糕。 - Dietrich Epp
@jogojapan,这有什么好处?首先你做一个像最大数字一样大的搜索,然后你说它是O(1)?我很确定你的算法比这里的答案中提到的任何其他穷举搜索要慢,所有这些搜索都在进行搜索直到必要,但是你为所有数据运行它。 - Saeed Amiri
@SaeedAmiri第一步不是 搜索。它是预先计算的。您预先计算了存在的172个数字(假设为64位整数)。 (顺便说一句,我用于预先计算的实现是天真的。每个数字增加的数字可以从先前计算的数字一步计算,例如 1+11+111 可以通过添加来计算 111 到先前计算的 1+11。但它并不重要,因为你只进行一次预计算)。该 影响 预先计算的是,以后您可以进行数百万次检查,每次检查只是一次哈希查找。 - jogojapan


简单详尽的搜索将起作用。

def is_digit_increasing_number(x):
    # n = 1, 1+11, 1+11+111, ...
    n = 1
    i = 1
    while n <= x:
        if x % n == 0 and n * 10 > x:
            return True
        i += 1
        n = n * 10 + i
    return False

2
2017-10-30 09:14





最简单的方法是添加(自下而上),我将使用简单的for循环:

List<int> numbersSum = new List<int>{1,2,3,4,5,6,7,8,9};
List<int> lastNumber = new List<int>{1,2,3,4,5,6,7,8,9};
for(int i=0;i<= lg n + 1;i++)
{

   for(int j=0;j<9;j++)
   {
      if(list[j] < n)
      {
          var lastNumberJ = lastNumber[j]*10+j+1;
          list[j] += lastNumberJ; // add numbers to see will be same as n.
          if (list[j] == n)
            return j+1;
          lastNumber[j] = lastNumberJ;
      }
   }   
}

return -1;

重要的是你最多只需要 log n 迭代,如果所有数字都大于给定数字,你也可以更快地返回,这是 O(log n) 算法。


2
2017-10-30 09:17



用于指出log-n界限的+1。 (那是10对数的基数,对吧?) - jogojapan
@jogojapan,实际上在2号或10号基础上并不重要,但我为10号基础写了它。 - Saeed Amiri
好的,那么也许我完全不明白。我认为重点是,如果给定的数字M等于一个总和 n + nn + nnn + ...,那么数量 n总和中的最后一个元素不能大于 log M。显然,对于基数10来说也是如此,因为否则最终元素将具有更多的小数位数 M 本身。如何在不同的基础上使用对数?特别是大于10的基数? - jogojapan
@jogojapan,你在正确的情况下是正确的,因此我写了我的假设是基数10,这是对数顺序的动机,但我用O表示法写的,不是精确的表示法,所以在O表示法之间没有区别登录基地10或基地2或...... - Saeed Amiri
哦,对,当然。我的意思是 lg n 在代码中,而不是 log n 在大哦符号。谢谢。 - jogojapan


这是一个python代码。这里的基本逻辑是,如果除以1-9之间的特定数字,则数字增加的数字给出仅由1组成的数字增加数。所有数字增加的数字1遵循特定模式,即12345678。 ..

import sys
for n in range(1,10):
    a=1
    if k%n!=0:
        a=0
    else:
        g=str(k/n)
        j=int(g[0])
        for i in range(1,len(g)):
            if int(g[i])==j+1:
                j=int(g[i])
            else:
                a=0
                break
    if a==1:
        print "Yes,it is a digit increasing number"
        sys.exit(0)
print "No,it is not a digit increasing number"

2
2017-11-01 03:36



非常好点! - jogojapan
我认为这比创建大量数字增加数字并比较我们得到的数字更加优化 - Tyranicangel
也许。对于你的方法中涉及的每个数字,仍然有几个计算步骤,我的答案的哈希值(你所指的,对吧?)可能在L1缓存中,因此提供了很高的速度。但是,是的,你的方法肯定非常好。这就是我赞成它的原因。 - jogojapan


一般代表是:

n +(n * 10 + n)+(n * 100 + n)......

如果数字看起来像相同数字的总和那么任何数字都可以表示为

(1 + 111 + ...)* base_digit

。假设我们可以使用简单的算法:

bool isDigitIncreasing(const int num)
{
    int n = 1;
    int sum = 1; //value to increase n
    while (n <= num) {
        //if num is (111...) * base_digit and base_digit is < 10
        if (num % n == 0 && n * 10 > num) return true;
        sum = sum * 10 + 1; //N*10+N where n is 1 as was assumed
        n += sum;  //next step
    }
    return false;
}

1
2017-10-30 09:35





Ambiguitiy: 值1-9是否为自己重复? (我自己懒得谷歌)

如果1-9重复,那么以下应该有效。如果没有,并且您希望代码仅在值> 10时工作,那么您可以初始化 mult 10。

int i, mult = 1, result, flag;

for( i=1; i<9; i++ )
{
    flag = 0;

    while( result < TARGET )
    {
        result = result+(i*mult);
        mult   = mult*10;

        if( result == TARGET )
        {
            flag = 1;
            break;
        }
    }
    if( flag == 1 )
        break;
}

执行后, i 必须包含RESULT为重复数字IF的值 flag 如果执行后标志为零,那么TARGET不是重复数字。

我想知道是否有可能一个数字可以重复多个值,只是好奇。


0
2017-10-30 09:18





这里 num 是数字和 n 是数字

#include<stdio.h>

int f(int num,int n)
{
 int d=n;
 while(num>0)
 {
        num-=n;
        n=d+n*10;
 }
 if(num==0)
        return 1;
 else
        return 0;
}

int main()
{
 int num;
 int n;
 int flag;
 printf("Enter the number :");
 scanf("%d",&num);
 printf("Enter the digit :");
 scanf("%d",&n);
 flag = f(num,n);
 if(flag == 1)
        printf("It's in n+nn+nnn+...\n");
 if(flag ==0)
        printf("It's not\n");
 return 0;
}

0
2017-10-30 09:34



我认为OP需要算法而无需输入基数 - Denis Ermolin
你可以尝试使用一个循环来检查每个基数 - Omkant
为什么是我?我不需要这个算法) - Denis Ermolin
@DenisErmolin:对不起,我的意思是OP,但这是我原生的打字方式 - Omkant


这是最短的解决方案

 public static int isDigitIncreasing (int n)
        {       
            if(n<10)
            {
                return 1;
            }

            for(int i=1;i<=9;i++)
            {
                int tempsum=i;
                int previous=i;
                while(tempsum<=n)
                {
                    previous=previous*10 + i;
                    tempsum=tempsum + previous;
                    if(tempsum==n)
                    {
                        return 1;
                    }
                }
            }

            return 0;
        }

0
2018-03-19 18:45





设d(k)为1 + 11 + 111 + ... +(11 ... 11),其中最后一个数字有k个数字。然后d(1)= 1,并且d(k + 1)= 10d(k)+ k + 1。

我们想测试d(k)* i = n,对于某些k,以及对于某些i = 1..9。

如果我们计算了d(k),则i(如果存在)必须是n / d(k)。我们可以通过将n与((n / d(k))%10)* d(k)进行比较来检查n / d(k)是否正确。如果i大于9,%10会使测试失败。

这给了我们一个相对简洁的解决方案:计算后续d(k)直到它们大于n,并且在每个点检查n是否是d(k)的数字倍数。

这是一个非常轻松的代码高尔夫实现的想法:

#include <stdio.h>

int is_digit_increasing(int n) {
    for(int d=1,k=1;d<=n;d=d*10+ ++k)if(n==(n/d)%10*d)return 1;
    return 0;
}

int main(int argc, char**argv) {
    for (int i=0; i<10000; i++) {
        if (is_digit_increasing(i)) {
            printf("%d\n", i);
        }
    }
    return 0;
}

0
2018-03-19 19:25





// Example program
#include <iostream>
#include <string>


int isDigitIncreasingNo(int n) {

    if(n<=0)
      return 0;

    int len = std::to_string(n).length();

    int vector1 = 0;
    int vector2 = 0;

    for(int i=1;i<=len;i++)
       vector2 = (vector2*10)+i;

    vector1 = vector2/10;

    if(n % vector2 == 0 && (n / vector2)<=9  )
        return 1;

    if(n % vector1 == 0 && (n / vector1)<=9  )
        return 1;

    return 0;
}

int main()
{
  for (int i=0; i<10000000; i++) {
        if (isDigitIncreasingNo(i)) {
            printf("%d\n", i);
        }
    }
    return 0;
}

0
2018-06-08 19:43