233 - Number of Digit One

Number of Digit One

  Total Accepted: 307   Total Submissions: 1853

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.


两经波折,一开始没想过会有大数的效率问题,后来发现,哦,原来考察的是找规律。

一开始的超时,最简单的解法:

        int countDigitOne(int n) {
                int sum = 0;
                for(int i = 1; i <= n; i++)
                        sum += count(i);
                return sum;
        }

        int count(int num) {
                int c = 0;
                while( num != 0 ) {
                        if(num % 10 == 1)
                                c++;
                        num = num / 10;
                }
                return c;
        }


超时后,参照了其他人的解法,努力去理解公式:

 ones += (a + 8) / 10 * m + (a % 10 == 1) * (b + 1);
发现,我的思路不对,肯定不能遍历所有比 n 小的数字啊,这样太慢了,因为是有规律可循的。

但是理解上述公式还是很困难的,我现在能够理解了,是经过自己拿数字去对应公式,比如3456这个数,利用这个公式去推导每一位可能为1的所有比该数小的数字个数的总和。

慢慢的理解,就积累了一道这样找规律的题目。另外,注意 a 和 b 要为 long型(这是细节)。

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值