数据结构与算法面试题80道(30)

30.在从1n的正数中1出现的次数

题目:输入一个整数n,求从1nn个整数的十进制表示中1出现的次数。

 

例如输入12,从112这些整数中包含的数字有11011121一共出现了5次。

分析:这是一道广为流传的google面试题。

 

最优美的算法就是按位进行分析

我们以21034来分析

如果将个位设为1,只考虑个位数上面的1,会有多少个1。(从1031->1021->1011->...->0001) 104个数包含104个1

如果将十位设为1,只考虑十位数上面的1,会有多少个1。(从101x->091x->...->001x)10*10个1,(x为0到9,不考虑个位上的1)

如果将百位设为1,只考虑百位数上面的1,会有多少个1。如果和刚才一样将百位设为1,发现千位只能为0,否则构成的数就比本身大了。

  那么如果百位为0,将百位设为1,会有多少个1。(01xx),包含x个1,这时候的x为100。

如果将千位设为1,只考虑千位数上面的1,会有多少个1。这时候也比较特殊,因为千位本来就为1。那么不仅要考虑万位有多少个数,还要考虑百位、十位、个位上有多少数。

  万位上只能是1,不能是2,如果为2,可能构成比本事大的数。那么千位为1,只考虑千位的1,会有多少1。

  1000+34个(万位为1,三位数有一千种组合;万位为2,后面三位数不能大于原来的数,所以是34)

如果将万位设为1,只考虑万位数上面的1,会有多少个1。0个,因为不存在十万位。

综上所述:将N分为高位,当前位,低位,1的个数为count。

如果当前位为0,count应该加上高位的值*低位的位数。

如果当前位为1,count应该加上高位的值*低位的位数,再加上低位的个数(低位的数值+1)

如果当前位大于1,count应该加上高位的个数*低位的位数

如果不明白,根据代码分析

 

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<stack>
using namespace std;
int howMachOne(int n){
    int count=0;//记录总共有多少个1
    int factor=1;//记录低位的位数
    int low;//记录低位的数值
    int current;//记录当前位数的值
    int hight;//记录高位的值
    while(n/factor!=0){
        low=n%factor;
        current=(n/factor)%10;
        hight=n/(factor*10);
        switch(current){
            case 0:
                count+=hight*factor;//高位的值*低位的位数
                break;
            case 1:
                count+=hight*factor+low+1;//高位的值*低位的个数+低位的个数
                break;
            default:
                count+=(hight+1)*factor;//高位的个数*低位的位数
                break;
        }
        factor*=10;
    }
    return count;
}

int main(){
    int count=howMachOne(12);
    cout<<count<<endl;
    return 0;
}

 

posted @ 2016-03-14 12:19  dreamOwn  阅读(333)  评论(0编辑  收藏  举报