编程之美 2.4 -----求1的数目

题目是这样的:给定一个正整数N,从1到N一共出现过多少个1?

如N=12,则f(12)=5,因为1,2,3,4,5,6,7,8,9,10,11,12共出现5次“1”。

书上的思路很巧妙,考虑到一个数字的每一位中1出现的次数,如果该位为0,则该位出现1的数目只与其前面的数字有关,如果为1,则与前面后面数字都有关,如大于1,仍只与前面数字有关。Java代码如下:

public void Book(){
    int n = num;
    int iCount = 0;
    int iFactor = 1;
    int iLowerNum = 0;
    int iCurrentNum = 0;
    int iHigherNum = 0;
   
    while(n/iFactor != 0){
    iLowerNum = n – (n / iFactor) * iFactor;
    iCurrentNum = n / iFactor % 10;
    iHigherNum = n / (iFactor * 10);
   
    switch(iCurrentNum){
    case 0:
    iCount += iHigherNum * iFactor;
    break;
    case 1:
    iCount += iHigherNum * iFactor + iLowerNum + 1;
    break;
default:
    iCount += (iHigherNum + 1) * iFactor;
    break;
    }
    iFactor *= 10;
    }
    System.out.println(“The biaozhun anwser is ” + iCount);
    }

自己的算法:

分别考虑不同位数的数字中1出现的个数。这种方法没有书上给出的简单,但是结果是正确的。

具体是这样的:

书中有公式:f(10^n – 1) = n * 10^(n – 1);即n位数中最多有1的个数是n*10^(n – 1),如3位数最大为999,从1至999共有 3 * 10 ^2 = 300个。

先给出一个N位数x,可以先利用上面公式求出(N – 1)位及以下所有数字中包含1的个数,剩下只需求解所有小于等于x的N位数中包含1的个数。

如x = 23435,先利用公式求出所有4位数中(1至9999)包含1的个数 ,为 4000个。然后求解10000到23435中1的个数。在求解N位数中包含1的个数时

需要注意某位前面的数字是有限制的,因为它是从最小的N位数10000(N个0)开始的。

具体代码如下:

    public void MyCal2(){
        int length = 0, tmp = num;
        //求出该数字的位数
        while(tmp > 0){
            length++;
            tmp /= 10;
        }
        System.out.println(“length = ” + length);
        //求出所有len – 1到1位的所有包含1的结果
        int sum = cal(length – 1);
        
        int pow = (int)Math.pow(10, length – 1);
        System.out.println(“The init result is ” + sum + “, the length = ” + 
        “, the pow = ” + pow);
        int current = num / pow;
        int pre = 0;
        int pos = num – current * pow;
        int left = (current == 1) ? (pos + 1): pow;
        
        for(int idx = length – 1; idx >= 1; idx–){
        //pow /= 10;
        pre = num / pow;
            current = (num – pre * pow )/(pow / 10);    
            pos = num % pow  – current * (pow / 10);
            
            System.out.println(“In the calculation2, the pre is ” + 
            pre + ”  current = ” + current + “, pos = ” + pos
            + “, pow = ” + pow );
            
            pre -= (int)Math.pow(10, length – idx -1);
            pre += 1;
            
            System.out.println(“After translation, the pre is ” + 
            pre );
            if(current > 1){
            left += pre * (int)Math.pow(10, idx – 1);
            } else if(current == 1){
            left += (pre – 1) * (int)Math.pow(10, idx – 1) + pos + 1;
            }else if(current == 0){
            left += (pre – 1) * (int)Math.pow(10, idx – 1);
            }
               pow /= 10;
        }
        System.out.println(“In the calculation2, the result is ” + (sum + left));
    }

    原文作者:maochongsandai110
    原文地址: https://blog.csdn.net/maochongsandai110/article/details/26623137
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞