Number of Digit One(leetcode 233)

Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.

For example:
Given n = 13,
Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.


1。 最笨方法, 从1到n,看一看每个数有多少个1,最后相加。超时
2。 有规律的
一位数中1个数 1
两位数中1个数 一位数*10 + 一位数个数(10的一次方)
三位数中1个数 两位数*10 + 两位数个数(10的二次方)

如果某一位为0 跳过
为1 为低位数的和+1
》=2 为 n*第几位
。。。。。。。。。。。。。。

对整数 abcdef
就是 0-f 中 1 + 0-e*10 中1 + 0- c* 10* 10 中1 。。。

class Solution {
public:
    int countDigitOne(int n) {
        if (n <= 0) {
            return 0;
        }
        vector<int> c;   // c[1]   一位数中1的个数
        // c[2]  两位数中1个数   。。。。。
        vector<int> num;    //输入的数转化为倒序int数组
        int total = 0;
        c.push_back(0);
        c.push_back(1);  // 0-9
        // 将数打散
        while (n != 0) {
            int t = n % 10;
            num.push_back(t);
            n = n / 10;
        }
        // 计算几位数应该有多少个1
        for(int i = 2; i < num.size(); ++i) {
            c.push_back(10*c[i-1] + gen10(i - 1));
        }
        for(int j = 0; j < num.size(); ++j) {
            total = total + (num[j]) * c[j];
            // 大于1
            if (num[j] > 1) {
                total += gen10(j);
            }
            // 为1  
            if (num[j] == 1) {
                int tmp = 0;
                for (int k = j - 1; k >= 0; --k) {
                    tmp = tmp * 10 + num[k];
                }
                total += tmp;
                total += 1;
            }
        }
        return total;
    }
    // 10的多少次方
    int gen10(int i) {
        int t = 1;
        for(int j = 0; j < i; ++j) {
            t*= 10;
        }
        return t;
    }
};

网上同样思路,不过公式化
以算百位上1为例子: 假设百位上是0, 1, 和 >=2 三种情况:

case 1: n=3141092, a= 31410, b=92. 计算百位上1的个数应该为 3141 *100 次.

case 2: n=3141192, a= 31411, b=92. 计算百位上1的个数应该为 3141 *100 + (92+1) 次.

case 3: n=3141592, a= 31415, b=92. 计算百位上1的个数应该为 (3141+1) *100 次.

以上三种情况可以用 一个公式概括:
(a + 8) / 10 * m + (a % 10 == 1) * (b + 1)

public class Solution {
    public int countDigitOne(int n) {
        int ones = 0;
        for (long m = 1; m <= n; m *= 10) {
            long a = n/m, b = n%m;
            ones += (a + 8) / 10 * m;
            if(a % 10 == 1) ones += b + 1;
        }
        return ones;
    }
}

http://www.2cto.com/kf/201507/415690.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值