(算法)从0到n整数中数字2出现的次数

题目:

数出0到n(含)中数字2出现了几次。

思路:

1、暴力方法,数出每个数字包含几个2,然后累加起来。

2、分析:分别考虑数字n每一位出现2的次数,如123123;

从左往右考虑4123123;

考虑第一个1(即第6位),该位出现2的次数为4*10^6/10;

考虑第一个2(即第5位),该位出现2的次数为41*10^5/10+3123+1;

考虑第一个3(即第4位),该位出现2的次数为(412+1)*10^4/10;

附:除以10的原因在于:每10个数字,任意位出现2的概率为1/10.

总结规律:

第i位出现2个次数与该位所在的数字有关:

当第i位的数字小于2,出现次数就等于比其高位部分的数字*10^i/10,

当第i位的数字等于2,出现次数就等于比其高位部分的数字*10^i/10+n%(10^i),

当第i位的数字大于2,出现次数就等于(比其高位部分的数字+1)*10^i/10。

代码:

#include<iostream>
#include<sstream>
#include<math.h>
using namespace std;

template<class out_T,class in_T>
out_T convert(const in_T &t){
    stringstream ss;
    out_T result;
    ss<<t;
    ss>>result;
    return result;
}

int count2sInRangeAtDigit(int number,int d){
    int powerOf10=pow(10,d);
    int nextPowerOf10=powerOf10*10;
    int right=number%powerOf10;

    int roundDown=number-number%nextPowerOf10;
    int roundUp=roundDown+nextPowerOf10;

    int digit=(number/powerOf10)%10;
    if(digit<2)
        return roundDown/10;
    else if(digit==2)
        return roundDown/10+right+1;
    else
        return roundUp/10;
}

int count2sInRange(int number){
    int count=0;
    string str;
    str=convert<string>(number);
    int len=str.size();

    for(int digit=0;digit<len;digit++)
        count+=count2sInRangeAtDigit(number,digit);
    return count;
}

int main(){
    int n;
    while(cin>>n){
        cout<<count2sInRange(n)<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AndyJee/p/4908899.html