LeetCodeOJ.Number of Digit One

试题请参见: https://leetcode.com/problems/number-of-digit-one/

题目概述

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-n循环, 累加每一个数字中1的个数. 于是妥妥的TLE.
然后就看到了某大神的思路:

每10个数, 有一个个位是1; 每100个数, 有10个十位是1; 每1000个数, 有100个百位是1.
因此可以使用一个循环, 计算每一位(个位,十位, 百位)上1的总个数.

举个栗子:

  1. 对于n=3141092, a = 31410, b = 92. 计算百位上1的个数应该为 3141 x 100 次;
  2. 对于n=3141192, a = 31411, b = 92. 计算百位上1的个数应该为 3141 x 100 + (92 + 1) 次;
  3. 对于n=3141592, a = 31415, b = 92. 计算百位上1的个数应该为 (3141 + 1) x 100次;

以上三个栗子分别代表了三种情况, 即百位上的数值x == 0, x == 1和x >= 2的情况.
因此对于某一位(个位,十位, 百位)上1的总个数可以使用如下公式:

(n / m + 8) / 10 * m + (n / m % 10 == 1) * (n % m + 1)

其中 m = 10, 100, 1000, etc.

遇到的问题

循环变量i必须为64位整型类型, 否则会溢出.

源代码

#include <iostream>

class Solution {
public:
    int countDigitOne(int n) {
        int numberOfOne = 0;

        for ( long long i = 1; i <= n; i *= 10 ) {
            int a = n / i, b = n % i;

            numberOfOne += ( a + 8 ) / 10 * i;
            if ( a % 10 == 1 ) {
                numberOfOne += b + 1;
            }
        }
        return numberOfOne;
    }
};

int main() {
    int n = 0;
    Solution s;

    std::cin >> n;
    std::cout << s.countDigitOne(n) << std::endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值