Algorithm 计算0和N之间的Ks数 问题:

Algorithm 计算0和N之间的Ks数 问题:,algorithm,numbers,range,time-complexity,counting,Algorithm,Numbers,Range,Time Complexity,Counting,我见过这样的问题: 这类问题非常类似于要求查找在数字范围[0,N]中显示的Ks(即K=0,1,2,…,9)的总数 例如: 输入:K=2,N=35 输出:14 详细信息:介于[0,35]之间的2列表:2,12,20,21,22,23,24,25,26,27,28,29,32,请注意22将计为两次(因为22包含两个2s) 我们所拥有的: 每个问题都有解决方案(如果您搜索,可以使用)。通常,O(logn)通过递归地考虑最高数字来解决此类问题需要时间,以此类推。计算0和N之间的2的数量的一

我见过这样的问题:

  • 这类问题非常类似于要求查找在数字范围
    [0,N]
    中显示的
    Ks(即K=0,1,2,…,9)
    的总数

    例如:

    • 输入:
      K=2,N=35
    • 输出:
      14
    • 详细信息:介于
      [0,35]
      之间的
      2
      列表:
      2,12,20,21,22,23,24,25,26,27,28,29,32
      ,请注意
      22
      将计为两次(因为
      22
      包含两个
      2
      s)

    我们所拥有的: 每个问题都有解决方案(如果您搜索,可以使用)。通常,
    O(logn)
    通过递归地考虑最高数字来解决此类问题需要时间,以此类推。计算0和N之间的2的数量的一个示例可以通过以下步骤解决(借用自):


    测试用例: 如果您想检查解决方案,以下是一些测试用例:

    • k=1,N=1
      :1
    • k=1,N=5
      :1
    • k=1,N=10
      :2
    • k=1,N=55
      :16
    • k=1,N=99
      :20
    • k=1,N=10000
      :4001
    • k=1,N=21345
      :18821
    • k=2,N=10
      :1
    • k=2,N=100
      :20
    • k=2,N=1000
      :300
    • k=2,N=2000
      :601
    • k=2,N=2145
      :781
    • k=2,N=3000
      :1900

    如果将整数转换为字符串,并通过该数组在循环中匹配字符串“k”,则可以执行此操作

    很简单。任何数字都可以在特殊记录中表示:

    73826=9999+6*(9999+1)+(3826+1)

    您需要计算这些数字的数字9、99、999、9999。。。然后您可以将它们放入数组中。特殊情况-如果为0,则使用数组[1,11,111,1111,…]


    请记住,第一个数字so也可能包含所需的值。

    对于情况0,我们需要单独处理

    对于1到9的一般情况:

    假设我们知道数字包含有x位数的k,并称之为m,要计算所有包含k且有(x+1)位数的数字,公式如下:

    9*m + (all_number_has_x_digit - m)
    
    原因很简单,对于所有已经包含k的数字,我们可以插入1到9作为第一个数字,所以我们有9*m。对于不包含k的所有数字,我们可以在它们前面添加k,这就创建了所有数字(数字为x,数字为-m)


    要计算从所有这些数字中出现的k的数量,公式应该是相似的(通过保持两个值:包含k的数字的数量和k的出现数量),这只是一个开始的想法:)

    可以通过算术完成

    编辑

    起初我没有看到您的代码示例。我的代码非常相似,只是输入是参数化的。所以答案是肯定的,它可以推广,但是你需要把0作为特例来处理

    如果给定的数字N是两位数,我们假设AB,我们计算的是数字K(1..9)

    您的示例输入:K=2,N=35

    5 is greater than 2 -> count = 1 (this is digit 2 in number 32)
    3 is greater than 2 -> count += 3 (this are twos in 2, 12, 22) + 10 (this are 20,21,22,23,24,25,26,27,28,29)
    *22 is counted twice
    
    所以我们计算1+3+10=14个2

    C代码示例(n=1..99,k=1..9):

    更新2

    因为k=0(包括0和n)更容易,所以只需要计算可被10、100、1000等整除的数字

    int numberOf0sBetween0AndN(int n)
    {
        int power = 1;            
        int counter = 1;
    
        while(power < n)
        {                
            power *= 10;
            counter += n / power;
        }
    
        return counter;
    }
    
    0和n之间的0的整数(整数n)
    {
    整数幂=1;
    int计数器=1;
    while(功率
    我相信这正是您需要的,简单、通用、快速

    下面是Python中的一个示例:

    慢检查器 检查程序很简单,使用
    string
    查找字符串中从“0”-“n”开始的所有数字,并计算
    k
    的匹配时间,速度很慢,但我们可以使用它检查其他解决方案

    import string       
    
    def knChecker( k, n ):
        ct = 0
        k = str(k)
        for i in xrange(0,n+1):
            ct += string.count(str(i),k)
        return ct   
    
    快速通解 K≠ 0 对于每个k=[1,9],很明显在[0,9]中我们可以在第一位找到1个匹配项

    在[0,99]中,我们可以在第一位找到1个匹配项,在第二位找到10个匹配项,所以都是1*10^1+10*10^0=20个匹配项

    在[0999]中,我们可以在第一位找到1个匹配项,在第二位找到10个匹配项,在第三位找到100个匹配项,所以所有匹配项都是1*10^2+10*10^1+100*10^0=300个匹配项

    因此我们很容易得出结论,在[0,10^l-1]中,存在
    l*10^(l-1)
    匹配

    更一般地说,我们可以在[0,f*10^l-1]中找到
    f*10^(l-1)*l
    匹配项

    因此,解决方案如下:

    例如,n='abcd',k='k'

    • 步骤1:如果n=0或n='',则返回0;计数“a000”中的匹配项,使用向上公式,l=len(n)
    • 步骤2a:如果a==k,我们知道所有的“bcd”都匹配,所以添加
      bcd
      matches
    • 步骤2b:如果a>k,我们知道所有的“k***”都匹配,所以添加
      10^(l-1)
      matches
    • 步骤3:剪切第一位a,并设置n=‘bcd’,转到步骤1
    这是k的代码≠ 0:

    def knSolver( k, n ):
        if k == '0':
            return knSolver0( n, 0 )
        if not n:
            return 0
        ct = 0
        n = int(n)
        k = int(k)
        l = len(str(n))
        f = int(str(n)[:1])
        if l > 1:
            ct += f * 10 ** (l-2) * (l-1)
        if f > k:
            ct += 10 ** (l-1)
        elif f == k:
            ct += n - f * 10 ** (l-1) + 1
        return ct + knSolver( k, str(n)[1:])
    
    k=0 k=0有点棘手,因为
    0***
    等于
    ***
    ,并且不允许对其进行计数,因为它是“0”

    那么k的解呢≠ 0不能适应k=0。但想法是相似的

    我们可以发现,如果n<100,则必须有
    n/10+1
    匹配项

    如果n在[100199]中,它与k非常相似≠ [0,99]中的0有20个匹配项

    如果[100999]中有n,则与k非常相似≠ [100999]中的0,有20*9个匹配项

    如果n在[10009999]中,它与k非常相似≠ [10009999]中的0有300*9个匹配项

    更一般地说,如果n在[10^l,k*10^l-1]中,它将具有
    l*10^(l-1)*k
    匹配项

    因此,解决方案如下:

    例如,n='abcd',k='0',递归步骤
    s
    =0

    • 步骤0:如果n='',则返回0;如果n<100,则返回
      n/10+1
    • 步骤1a:n='f(…)'
      int numberOfKsBetween0AndN (int n, int k)        
      {
          int power = 1;
          int counter = 0;
      
          while (n > 0)
          {
              int d = n % 10;
              n /= 10;
      
              counter += (d < k ? 0 : power) + d * power / 10;
              power *= 10;
          }
      
         return counter;
      }
      
          int numberOfKsBetween0AndN (int n, int k)   
          { 
              int originalNumber = n;
              int power = 1;
              int i = 0;
              int counter = 0;            
      
              while (n > 0)
              {
                  int d = n % 10;
                  n /= 10;
      
                  counter += d * (power * i) / 10;
      
                  if (d > k)
                      counter += power;
                  else if (d == k)
                      counter += originalNumber % power + 1;
      
                  power *= 10;
                  i++;
              }
      
              return counter;
          }
      
      int numberOf0sBetween0AndN(int n)
      {
          int power = 1;            
          int counter = 1;
      
          while(power < n)
          {                
              power *= 10;
              counter += n / power;
          }
      
          return counter;
      }
      
      import string       
      
      def knChecker( k, n ):
          ct = 0
          k = str(k)
          for i in xrange(0,n+1):
              ct += string.count(str(i),k)
          return ct   
      
      def knSolver( k, n ):
          if k == '0':
              return knSolver0( n, 0 )
          if not n:
              return 0
          ct = 0
          n = int(n)
          k = int(k)
          l = len(str(n))
          f = int(str(n)[:1])
          if l > 1:
              ct += f * 10 ** (l-2) * (l-1)
          if f > k:
              ct += 10 ** (l-1)
          elif f == k:
              ct += n - f * 10 ** (l-1) + 1
          return ct + knSolver( k, str(n)[1:])
      
      def knSolver0( n, s ):
          if n == '':
              return 0
          ct = 0
          sn = str(n)
          l = len(sn)
          f = int(sn[:1])
          n = int(n)
          if n < 100 and s == 0:
              return n / 10 + 1
          if s > 0 and f > 0:
              ct += 10 ** (l-1) + (l-1) * 10 ** (l-2)
          elif s > 0 and f == 0:
              ct += n + 1
          if n >= 100 and s == 0:
              ct += 10
              for i in xrange(2,l):
                  if i == l-1:
                      ct += i * 10 ** (i-1) * (f-1)
                  else:
                      ct += i * 10 ** (i-1) * 9
          elif s > 0 and f != 0:
              ct += (f-1) * 10 ** (l-2) * (l-1)
          return int(ct + knSolver0( sn[1:], s+1 ))
      
      print "begin check..."
      for k in xrange(0,10):
          sk = str(k)
          for i in xrange(0,10000):
              #knSolver( sk, i )
              if knChecker( sk, i ) != knSolver( sk, i ):
                  print i, knChecker( sk, i ) , knSolver( sk, i )
      print "check end!"
      
      //_k --> pattern
      //_n range
      
      Regex r = new Regex(_k.ToString(), RegexOptions.IgnoreCase);
              int count = 0;
      
              for (int i = 0; i <= _n; i++)
              {
                  MatchCollection m = r.Matches(i.ToString());
                  foreach(Match _m in m)
                  { 
                  if (_m.Success)
                  {
                      count += 1;
                  }
                  }
      
              }
      
              Console.WriteLine(count);