剑指Offer:JZ31 - 整数中1出现的个数(从1到n整数中1出现的次数)(解题思路+Java代码)

JZ31 - 整数中1出现的个数(从1到n整数中1出现的次数)

题目:求出1-13的整数中1出现的次数,并算出100-1300的整数中1出现的次数?为此他特别数了一下1-13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

解题思路:

  • 将n分成高位和低位两部分,从各位开始、十位、百位…进行分割,十位以上思想相同,这里拿十位和个位说区别;
  • 个位:有2种情况,第一种只要个位大于等于1就可以增加一个1;第二种是0没有1,例如1-71中个位有8个1,70中个位有7个1,即(x+9)/10 1即可解决;
  • 十位:有3中情况,第一种为0,没有1;第二种等于1,这样这块的数字就由低位数字决定个数了,例如1-17中十位有8个1(数量为低位数字7+1);第三种情况大于等于2,十位就包含10个1,例如(20中十位有10个1,120中十位有20个1)在这两个例子中高为分别为2和12,即(x+8)/10*10即可;
  • 百位、千位…同十位处理方法一样。
  • 这里将十位中的(x+8)和个位中的(x+9)做一下统一,个位末尾大于等于1的情况是不是可以看成十位中的第二种情况和第三种情况呢,为1时只不过低位为0,低位+1还是1 。而大于等于2时直接(x+8)/10 *1也可以加1 。这样就将所有位置都统一了,代码如下:
/**
 * @author 枫叶火火
 */
public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        //1的数量
        int num = 0;
        //每次增长一位
        for(int i = 1 ; i <= n ; i*=10){
            //分割数字
            //高位
            int high = n / i;
            //低位,i代表个位时,个位下面对1取余就是0
            int low = n % i;
            //先计算整的,高位最后一位达到2就可以进位,当前位就有乘i个1,这里达到1但是每到2的另算,数量和低位有关
            num +=(high + 8)/10 * i;
            //当高位的最后一位为1就是上面说的那种情况,就应该再加上这几个当前位带有1的数量也就是低位+1(10~16只看10位有7个1)
            if(high % 10 == 1){
                num += low + 1;
            }
        }
        return num;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值