某个数字出现的次数

来源:互联网 发布:东方中原电子白板软件 编辑:程序博客网 时间:2024/05/16 14:44

http://bbs.chinaunix.net/thread-1191740-1-2.html
有个网友提问。

本人写了个程序,基本可以解决这个问题。
题目:
写一个函数f(n),能得到0到1234567890之间的任意一个数中出现1的次数
例如f(0)=0,f(1)=1,f(12)=5

本人把她扩展了一下,她可以查到任意10个数字出现的次数。她可以自定义开始和结束点,
_findOneOf0_9NumberAppearsTimes_method_2()只要在封装一次其实也是可以使用开始和结束点的,这里本人就不给出了。其实还可以在扩展成对于任意进制适用的,不只适用于10进制,这个我也不给出了。
不过_findOneOf0_9NumberAppearsTimes_method_2()对于“边界值”的计算可能出现出现问题,如果出现问题,请给本人留言或写信(cpdoor@163.com )指出。

这里本人提供了两个函数
findOneOf0_9NumberAppearsTimes_method_1()和_findOneOf0_9NumberAppearsTimes_method_2()
都可以得出结果。不过显然前者和后者的执行时间差很多!就像提问的那样,在计算
1234567890
时,这个优势就显示出来了。其实
_findOneOf0_9NumberAppearsTimes_method_2()
还是不是最快的!我能想到最快的方法是利用查表的方法,就是事先把结果存在一个表中,这应该是最快的,不过前期要准备一下!呵呵!

findOneOf0_9NumberAppearsTimes_method_1()
的基本原理就是正常的穷举遍历,可以很正确,但是一定是最慢的。

_findOneOf0_9NumberAppearsTimes_method_2()
的基本原理就是KEY按照个位,十位,百位...出现的次数和就是KEY出现的次数了。

PS:
任何关于更快的修改意见和扩展性(扩展到不同制式,比如16进制)的建议留言都是欢迎的。
//=============================================================================
// 10^n, value of 10's power N
int _10_power_N( const int iN )
{
    int iTemp = 1;
    for( int i = iN; i > 0; --i )
    {
        iTemp *= 10;
    }
    return iTemp;
}

// compute number digit
int digitIs( int iN )
{
    int iDigit = 0;
    do
    {
        ++iDigit;
        iN /= 10;
    }while( iN > 0 );

    return iDigit;
}

// Find one of the [0-9] number appears times, whose zone is from iBegin to iEnd
// The Basic method for this question, which called method_1
int findOneOf0_9NumberAppearsTimes_method_1( const int iKey ,const int iBegin, const int iEnd )
{
    int iTimes = 0;
    int iTemp = 0;
    int iTempI = 0;
#ifdef _DEBUG
    int iTempEnd = iEnd;
    int iLongest = digitIs( iTempEnd );
    int iLowestDigit = 0;
    int iMiddleDigit = 0;
    int iHighestDigit = 0;
#endif // _DEBUG

    for( int i = iBegin; i <= iEnd; ++i )
    {
        iTempI = i;
        do{
            iTemp = iTempI % 10;
            if( iTemp == iKey )
            {
                ++iTimes;

#ifdef _DEBUG
                int iDigit_iTempI = digitIs( iTempI );
                int iDigit_i = digitIs( i );
                if( iDigit_iTempI == iDigit_i )
                {
                    ++iLowestDigit;
                }
                else if( ( iDigit_i == iLongest ) && ( iDigit_iTempI == 1 ) )
                {
                    ++iHighestDigit;
                }
                else
                {
                    ++iMiddleDigit;
                }
#endif // _DEBUG

            }
            iTempI /=10;
        }while( iTempI != 0 );
    }

#ifdef _DEBUG
    printf( "Lowest:%d, Middle:%d, Highest:%d\t", iLowestDigit, iMiddleDigit, iHighestDigit );
#endif // _DEBUG

    return iTimes;
}

int _findOneOf0_9NumberAppearsTimes_method_2( const int iKey ,const int iEnd )
{
    int iTimes = 0;
    int iDigit = 0;
    int iTempEnd = iEnd;
    int iLastTempEnd = iEnd;
    int iTemp = 0;
#ifdef _DEBUG
    int iLowestDigit = 0;
    int iMiddleDigit = 0;
    int iHighestDigit = 0;
#endif // _DEBUG

    iDigit = digitIs( iTempEnd );

    if( iKey == 0 )
    {
        for( int i = 0; i < ( iDigit -1 ); ++i )
        {
            if( i == 0 )
            {
                // lowest digit
                if( ( iTempEnd % 10 ) > iKey )
                {
                    iTemp = iTempEnd / 10 + 1;
                    iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                    iLowestDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
                }
                else if( ( iTempEnd % 10 ) == iKey )
                {
                    iTemp = iTempEnd / 10 + 1;
                    iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                    iLowestDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
                }
                else
                {
                    iTemp = iTempEnd / 10;
                    iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                    iLowestDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
                }
            }
            else
            {
                // other middle digits
                if( ( iTempEnd % 10 ) > iKey )
                {
                    iTemp = iTempEnd / 10;
                    iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                    iMiddleDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
                }
                else if( ( iTempEnd % 10 ) == iKey )
                {
                    iTemp = iTempEnd / 10;
                    iTimes += ( ( iTemp - 1 ) * _10_power_N( i - 0 ) );
#ifdef _DEBUG
                    iMiddleDigit += ( ( iTemp - 1 ) * _10_power_N( i - 0
                        ) );
#endif // _DEBUG
                    iTimes += ( iEnd - iTempEnd * _10_power_N( i - 0 ) + 1 );
#ifdef _DEBUG
                    iMiddleDigit += ( iEnd - iTempEnd * _10_power_N( i - 0 ) + 1 );
#endif // _DEBUG
                }
                else
                {
                    iTemp = iTempEnd / 10;
                    iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                    iMiddleDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
                }
            }

            iLastTempEnd = iTempEnd;
            iTempEnd /= 10;
        }
#ifdef _DEBUG
        printf( "Lowest:%d, Middle:%d, Highest:%d\t", iLowestDigit, iMiddleDigit, iHighestDigit );
#endif // _DEBUG

        return iTimes;
    }

    for( int i = 0; i < ( iDigit -1 ); ++i )
    {
        if( i == 0 )
        {
            // lowest digit
            if( ( iTempEnd % 10 ) > iKey )
            {
                iTemp = iTempEnd / 10 + 1;
                iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                iLowestDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
            }
            else if( ( iTempEnd % 10 ) == iKey )
            {
                iTemp = iTempEnd / 10 + 1;
                iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                iLowestDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
            }
            else
            {
                iTemp = iTempEnd / 10;
                iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                iLowestDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
            }
        }
        else
        {
            // other middle digits
            if( ( iTempEnd % 10 ) > iKey )
            {
                iTemp = iTempEnd / 10 + 1;
                iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                iMiddleDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
            }
            else if( ( iTempEnd % 10 ) == iKey )
            {
                iTemp = iTempEnd / 10;
                iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                iMiddleDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
                iTimes += ( iEnd - iTempEnd * _10_power_N( i - 0 ) + 1 );
#ifdef _DEBUG
                iMiddleDigit += ( iEnd - iTempEnd * _10_power_N( i - 0 ) + 1 );
#endif // _DEBUG
            }
            else
            {
                iTemp = iTempEnd / 10;
                iTimes += ( iTemp * _10_power_N( i ) );
#ifdef _DEBUG
                iMiddleDigit += ( iTemp * _10_power_N( i ) );
#endif // _DEBUG
            }
        }

        iLastTempEnd = iTempEnd;
        iTempEnd /= 10;
    }

    // highest digit
    iTemp = iEnd / _10_power_N( iDigit -1 );
    if( iTemp > iKey )
    {
        iTimes += _10_power_N( iDigit - 1 );
#ifdef _DEBUG
        iHighestDigit += _10_power_N( iDigit - 1 );
#endif // _DEBUG
    }
    else if( iTemp == iKey )
    {
        iTimes += ( iEnd - iTemp * _10_power_N( iDigit -1 ) + 1 );
#ifdef _DEBUG
        iHighestDigit += ( iEnd - iTemp * _10_power_N( iDigit -1 ) + 1 );
#endif // _DEBUG
    }

#ifdef _DEBUG
    printf( "Lowest:%d, Middle:%d, Highest:%d\t", iLowestDigit, iMiddleDigit, iHighestDigit );
#endif // _DEBUG

    return iTimes;
}

int main(int argc, _TCHAR* argv[])
{
    int iN;
    int iBegin = 0;
    int iEnd = 1004 ;

    printf(" %d - %d\n", iBegin, iEnd );

    for( int i = 0; i < 10; ++i )
    {
        printf( "==============================================================\n" );
#ifdef _DEBUG
        iN = findOneOf0_9NumberAppearsTimes_method_1( i, iBegin, iEnd );
        printf( "-> %d %d\n", i, iN );
#endif // _DEBUG

        iN = _findOneOf0_9NumberAppearsTimes_method_2( i, iEnd );
        printf( "#-> %d %d\n", i, iN );
    }

    getchar();

    return 0;
}

原创粉丝点击