微软面试100题---求出从1到n的正数中1出现的次数

题目

输入一个整数n,求从1到n这n个整数的十进制表示中1出现从次数。
例如输入12,从1到12这12个数中包含1的数字:1,10,11,12;1总共出现了5次;

实现

思路:求出一个数中1的个数,可以使用除法、取余;求1到n的n个数,循环==此方法n较大时,费时;
高效方法:分别求出每位出现1的次数,再将每位出现1 的次数相加;

分析:
假设数字为abcde;我们分析百位出现1的次数:
1)当c=0, ab0de
百位出现1的:
00100–00199
01100–01199
…….
(ab-1)100–(ab-1)199
所以一共:ab*100+0

2)当c=1,ab1de
百位出现1的:
除了1)中的之外,(ab-1)200–ab1de之间出现1的:
ab100–ab1de
所以一共:ab*100+(de+1)

3)当c>1,比如ab3de
除了1)中的之外,(ab-1)200–ab3de之间出现1的:
ab100–ab199
所以一共:ab*100+(100)

===>
个位出现1的次数=n/10+(个位=0,0;个位>1,1;个位=1,1)
十位出现1的次数=n/100+(十位=0,0;十位>1,10;十位=1,个位数字+1)
百位出现1的次数=n/1000+(百位=0,0;百位>1,100;低二位+1)
…….

代码实现:

public static int countOf1(int n){
        int num=n;
        int N=0;
        //计算n的位数
        while(num!=0){
            num=num/10;
            N++;
        }
        int count=0;
        //遍历每一位
        for(int i=1;i<=N;i++){
            count+=n/test(i)*test(i-1);
            int temp=n/test(i-1)%10;  //第i位数字
            if(temp==1){
                count+=n%test(i-1)+1;//n%test(i-1)
            }
            if(temp>1){
                count+=test(i-1);
            }
        }   
        return count;
    }

    /*
     * num=1--1
     * num=2--10
     * num=3--1000
     * ......
     * 第num位为多少?
     */
    private static int test(int num) {
        if(num==0){
            return 1;
        }
        int res=1;
        for(int i=1;i<=num;i++){
            res=res*10;
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值