Chinaunix首页 | 论坛 | 博客
  • 博客访问: 283709
  • 博文数量: 58
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 600
  • 用 户 组: 普通用户
  • 注册时间: 2015-11-27 08:37
个人简介

从linux了解世界

文章分类
文章存档

2017年(5)

2016年(51)

2015年(2)

我的朋友

分类: Java

2016-08-25 15:50:26

leetcode上看到了一个智商爆表的解法:
public int countDigitOne(int n) {
    int ones = 0;
    for (long m = 1; m <= n; m *= 10)
        ones += (n/m + 8) / 10 * m + (n/m % 10 == 1 ? n%m + 1 : 0);
    return ones;
}
现在使用a和b两个变量来解释该算法:
int countDigitOne(int n) {
    int ones = 0;
    for (long long m = 1; m <= n; m *= 10) {
        int a = n/m, b = n%m;
        ones += (a + 8) / 10 * m +( a % 10 == 1 ? (b + 1):0);
    }
    return ones;
}
通过m求从1到n中,每个十进制位出现1的次数,m取值1,10,100...为了求每个十进制位出现1的次数,我们把n分成两个部分,例如当用m=100来把n=3141592分成a=31415和b=92两个部分,求百位出现1的次数。此时把从1到3141592的数中,百位为1的数看做oooo1xx,其中oooo可以从0到3141,xx可以从0到99。因此百位的1出现3142*100次,也就是(a/10+1)*m

再把m取1000判断千位上1出现的次数,同样的把n分成a=3141和b=592两个部分。把从1到3141592的数中,千位为1的数看做ooo1xxx,当ooo从0到313,xxx可以从0到999,当ooo是314的时候,xxx只可以从0到592了。因此千位的1出现313*1000+593次,也就是(a/10)*m+(b+1)。

因此我们可以知道当a的个位为2及以上时,次数是(a/10+1)*m。a的个位为1时,次数是(a/10)*m+(b+1)。a的个位为0时,次数是(a/10)*m。上三种情况可以得到(a + 8) / 10 * m + (a % 10 == 1) ? (b + 1):0;

ps:原文地址:https://discuss.leetcode.com/topic/18054/4-lines-o-log-n-c-java-python
自己在翻译的基础上加入了自己的理解,并修改了一些用来描述的代码和表述
阅读(2638) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~