《剑指offer》刷题——【时间效率】面试题43:1~n整数中1出现的次数(java实现)

《剑指offer》刷题——【时间效率】面试题43:1~n整数中1出现的次数(java实现)

一、题目描述

输入一个整数n,求1~n这n个整数的十进制表示中1出现的次数,例如,输入12,1~12这些整数中包含
1的数字有1,10,11,12,1一共出现5次

二、题目分析

方法一:不考虑时间效率

  • 累加1~n中每个整数1出现的次数(每次通过对10求余数判断整数的个位数字是不是1,若此数字大于10,则除以10以后再判断个位数字是不是1)
public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        int number = 0;
        for(int i=1;i<=n;i++){
            number+=NumberOf1(i);
        }
        return number;
    }
    /**
    * 一个数字包含1的个数
    */
    public int NumberOf1(int n){
        int number =0;
        while(n!=0){
            if(n % 10==1){
                number++;
            }
            n = n/10;
        }
        return number;
    }
}

方法二:推荐

  • 若第i位(从低位向高位开始)上的数字为0,则第i位可能出现1的次数仅由更高位决定(若无最高位,则视为0),等于更高位数字当前位数的权重10^(i-1);

  • 若第i位上的数字为1,则第i位上可能出现1的次数不仅受更高位影响,还受低位影响(若无最低位,则视为0),等于更高位数字当前位数的权重10^(i-1)+(低位数字+1)

  • 若第i位上的数字大于1,则第i位上可能出现1的次数仅由更高位决定,等于(更高位+1)*当前位数的权重10^(i-1)

  • 规律:(以下X仅指1~9)
    - 1~10,个位数,任意的X都出现1次
    - 1~100,十位数,任意X都出现10次
    - 1~1000,百位数,任意X都出现100次
    - ……
    - 1~10^i,左数第二位(右数第i位),任意X都出现 10^(i-1)

  • 例:21345

    • 个位:1~21340,1出现2134次,21341中1出现一次,故 (2134+1)*10^(i-1)=2135
    • 十位:1~21300,1出现213次;21301 ~21345,4>1, 十位1出现10次,故(213+1)*10^(2-1)=2140
    • 百位:1~21000,1出现21次,;21001 ~21345,3>1,百位1出现100次,故(21+1)*10^(3-1)=2200
    • 千位:1~20000,1出现2次;20001 ~21345,1=1,1出现345次,故2*10^(4-1)+345=2345
    • 万位:2>1,1出现次数1*10^(5-1)=10000
    • 总:2135+2140+2200+2345+10000=18820
  • 总结:

    • 取第i 位左边的数字(高位),乘以10 ^(i−1) ,得到基础值a
    • 取第i 位数字,计算修正值:
      • 如果大于X,则结果为a+ 10 ^(i−1)
      • 如果小于X,则结果为a
      • 如果等X,则取第i 位右边(低位)数字,设为b ,最后结果为a+b+1
public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        int curr;//当前位
        int low;//低位
        int temp;
        int high=n;//高位
        int i=1;//遍历到的当前位,从最低位开始
        int total=0;//总次数
        while(high!=0){
            high = n/(int)Math.pow(10,i);//获取第i位的高位
            temp = n%(int)Math.pow(10,i);//
            curr = temp/(int)Math.pow(10,i-1);//获取第i位
            low = temp%(int)Math.pow(10,i-1);//获取第i位的低位
            //第i位数为1
            if(curr==1){
                total+=high*(int)Math.pow(10,i-1)+low+1;
            }
            else if(curr<1){
                total+=high*(int)Math.pow(10,i-1);
            }
            else{
                total+=(high+1)*(int)Math.pow(10,i-1);
            }
            i++;
        }
        return total;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值