Leetcode 233 Number of Digit One

1. 问题描述

  给定一个整数n,在所有不大于n的非负整数中,计算包含数字1的整数的个数。例如 n=13 的结果为6,包含1的数字有1,10,11,12,13。


2. 方法与思路

  这个问题最直观的方法就是累加1到n所有的包含1的数的个数。每个数通过循环取余10的方法判断是否包含1。但是这种思路效率并不高,数字n有 logn 位,总得时间复杂度为 O(nlogn)
  利用数字的规律,简化计算。以数字21567为例。先将数字分为两段:“1到1567”和“1568到21567”。
  从1568到21567这段,分为两种情况,1出现在最高位的情况。从10000到19999的数字中,包含1的一共出现了 104 个,但对于数字12345,1出现在10000到12345的万位的个数就是 2345+1=2346 次。再看1出现在从1568到21567后4位的情况。同样分成两段,1568到11568和11569到21568,每一段剩下的4位书中,设其中一位是1,其他三位可以是0~9之间的数,根据排列组合原理处理即可。
  至于从1到1567利用递归就可以了。
  

class Solution {
private:
    int numofOne(int n)
    {
        if(n == 0) return 0;
        if(n > 0 && n < 10) return 1;

        int a = n,cnt = 0,num1,num2,num3;

        while(a/10)
        {
            a /=10;
            cnt++;
        }

        if(a > 1)
            num1 = pow(10,cnt);
        else if(a == 1)
            num1 = n%(int)pow(10,cnt)+1;

        num2 = a * (cnt)*pow(10,cnt-1);
        num3 = numofOne(n%(int)pow(10,cnt));

        return num1+num2+num3;

    }
public:
    int countDigitOne(int n) {
        return numofOne(n);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值