【问题标题】:Digit-increasing number test数字递增测试
【发布时间】:2012-10-19 12:23:09
【问题描述】:

如果一个数字等于 n + nn + nnn + ... 对于 1 和 9 之间的某个数字 n,则称为数字递增。例如,24 是数字递增的,因为它等于 2 + 22(这里 n = 2 )。

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

【问题讨论】:

  • 如果您不需要特定语言的答案,我会回答。
  • 我只想要逻辑。任何语言的代码都可以。
  • 您只有 9 个选项可供尝试。它是 (1+11+...)(2+22+...)... 或 (9+99+...)
  • 您可以使用模/除法进行数字分离。例如,24/10=2 然后将其乘以 10 得到 20。然后将商 '2' 加到这个 '20' 上得到' 22'。现在尝试再次将'22'添加到商然后你得到24。如果它等于给定的数字那么它是数字增加的。只需将其概括为 N 位数。很简单。
  • 为什么要关闭它。我在 C 语言中只有一个有效的答案...

标签: c++ c algorithm logic


【解决方案1】:

具有此属性的数字相对较少:在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 类型的组合 @987654325 @ 表示长度之和 K

【讨论】:

  • 当 n 被限制为某个常数时,每个 O(n) 算法都是 O(1)。
  • @SaeedAmiri 这不是重点。关键是哈希中的查找不取决于您查找的数字的大小,甚至不取决于条目的数量。 (后者不完全正确,取决于哈希如何处理冲突。这就是为什么我说虚拟 O(1)。)
  • 在 Python 中,对于整数,hash(x) == x,所以很容易有一些冲突非常糟糕。
  • @jogojapan,这样做有什么好处?起初你搜索最大数字,然后你说它是O(1)?我很确定您的算法比此处答案中提供的任何其他详尽搜索都慢,所有这些算法都在进行搜索直到必要,但是您为所有数据运行它。
  • @SaeedAmiri 第一步不是搜索。是预计算。您预先计算了 172 个存在的数字(假设为 64 位整数)。 (顺便说一句,我用于预计算的实现是幼稚的。每个数字增加的数字都可以从先前计算的一个步骤中计算出来,例如 1+11+111 可以通过将 111 添加到先前计算计算1+11。但这并不重要,因为您只进行一次预计算)。预计算的效果是以后可以做数百万次的数字检查,每次检查只是哈希查找。
【解决方案2】:

一般表示为:

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;
}

【讨论】:

    【解决方案3】:

    简单的详尽搜索就可以了。

    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
    

    【讨论】:

      【解决方案4】:

      最简单的方法是进行加法(自下而上),我将使用简单的 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)算法。

      【讨论】:

      • +1 用于指出 log-n 界限。 (这是一个以 10 为底的对数,对吧?)
      • @jogojapan,实际上以 2 或 10 为底并不重要,但我是为 10 写的。
      • 好吧,那我可能没完全理解。我认为关键是如果给定的数字 M 等于和 n + nn + nnn + ...,那么和的最后一个元素中的 n 的数量不能大于 log M。显然这对于​​以 10 为底的情况是正确的,因为否则最终元素的小数位数将比 M 本身多。这将如何与不同基数的对数一起工作?特别是大于 10 的基数?
      • @jogojapan,你在确切的情况下是对的,因此我写了我的假设以 10 为底,这是对数顺序的动机,但我用 O 表示法而不是精确表示法写它,所以在 O 表示法中,以 10 为底数或以 2 为底数或 ...
      • 哦,对,当然。我的意思是代码中的lg n,而不是大哦符号中的log n。谢谢。
      【解决方案5】:

      这是一个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"
      

      【讨论】:

      • 我认为这比创建大量数字递增数字并将我们得到的数字与它们进行比较更优化
      • 也许吧。您的方法中涉及的每个数字仍然有几个计算步骤,并且我的答案的哈希(这就是您所指的,对吗?)很可能在 L1 缓存中,从而提供了极快的速度。但是,是的,你的方法绝对是非常好的。这就是我投赞成票的原因。
      【解决方案6】:

      我就是这样做的。签出一次。

      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;
          }
      

      【讨论】:

      • 不必要的复杂。
      【解决方案7】:

      这是最短的解决方案

       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;
              }
      

      【讨论】:

        【解决方案8】:

        歧义:值 1-9 是否重复? (懒得自己google了)

        如果 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 为重复数的值,如果 flag 为 1。如果执行后 flag 为零,则 TARGET 不是重复数。

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

        【讨论】:

          【解决方案9】:

          这里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;
          }
          

          【讨论】:

          • 我认为OP想要算法而不需要输入基数
          • 你可以尝试使用一个循环来检查每个基数
          • 为什么是我?我不需要这个算法)
          • @DenisErmolin :对不起,我的意思是 OP,但这是我的原生打字风格
          【解决方案10】:

          令 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;
          }
          

          【讨论】:

            【解决方案11】:
            // 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;
            }
            

            【讨论】:

              【解决方案12】:
               public boolean isDigitIncreasing(int number)
              
               {
                int sum;
                int size=calculateNumberOfDigits(number);
              
                for(int i=1;i<=9;i++)
                 {
                    sum=0;
                    int temp=size;
                    while(temp>=1)
                      {
                          for(int j=temp;j<=1;j--)
                           {
                              sum=sum+i*(int)Math.pow(10,j-1);
                           }
                          temp--;
                       }
                    if(sum==number)
                     {
                        return true;//Its a digit increasing
                      }
                  }
              
                   return false;
                }
              
               public int calculateNumberOfDigits(int number)
                {
                   int size=0;
                   do
                     {
                           number=number/10;
                           size++;
                      }while(size>0);
              
                     return size;
                }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-04-29
                • 1970-01-01
                • 2020-07-04
                • 1970-01-01
                • 2016-09-05
                • 1970-01-01
                相关资源
                最近更新 更多