• 《剑指offer》第四十三题(从1到n整数中1出现的次数)


    // 面试题43:从1到n整数中1出现的次数
    // 题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如
    // 输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。
    
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    
    // ====================方法一====================
    //逐个判断,时间复杂度为O(nlogn),不好
    int NumberOf1(unsigned int n);
    
    int NumberOf1Between1AndN_Solution1(unsigned int n)
    {
        int number = 0;
    
        for (unsigned int i = 1; i <= n; ++i)
            number += NumberOf1(i);
    
        return number;
    }
    
    int NumberOf1(unsigned int n)
    {
        int number = 0;
        while (n)
        {
            if (n % 10 == 1)
                number++;
    
            n = n / 10;
        }
    
        return number;
    }
    
    // ====================方法二====================
    int NumberOf1(const char* strN);
    int PowerBase10(unsigned int n);
    
    int NumberOf1Between1AndN_Solution2(int n)//把数字换成字符串,方便处理
    {
        if (n <= 0)
            return 0;
    
        char strN[50];
        sprintf(strN, "%d", n);//格式化输出成字符串
    
        return NumberOf1(strN);
    }
    
    int NumberOf1(const char* strN)
    {
        if (!strN || *strN < '0' || *strN > '9' || *strN == '')
            return 0;
    
        int first = *strN - '0';//第一位的最大值
        unsigned int length = static_cast<unsigned int>(strlen(strN));//强制转换符
    
        if (length == 1 && first == 0)//边界特殊情况
            return 0;
    
        if (length == 1 && first > 0)
            return 1;
    
        // 假设strN是"21345"
        //先计算第一种情况,第一位为1的个数
        // numFirstDigit是数字10000-19999的第一个位中1的数目
        int numFirstDigit = 0;
        if (first > 1)
            numFirstDigit = PowerBase10(length - 1);
        else if (first == 1)
            numFirstDigit = atoi(strN + 1) + 1;//若在1xx的情况,个数不到PowerBase10(length - 1),atoi是字符串转整数
    
        //第二种情况,非第一位为1的个数
        // numOtherDigits是01346-21345除了第一位之外的数位中1的数目
        int numOtherDigits = first * (length - 1) * PowerBase10(length - 2);//第一位可能性有first个,第二项表示选取除了第一位的任一位为1,剩下的有10种可能
        // numRecursive是1-1345中1的数目,使用迭代处理
        int numRecursive = NumberOf1(strN + 1);
    
        return numFirstDigit + numOtherDigits + numRecursive;
    }
    
    int PowerBase10(unsigned int n)//10的n次方
    {
        int result = 1;
        for (unsigned int i = 0; i < n; ++i)
            result *= 10;
    
        return result;
    }
    
    // ====================测试代码====================
    void Test(const char* testName, int n, int expected)
    {
        if (testName != nullptr)
            printf("%s begins: 
    ", testName);
    
        if (NumberOf1Between1AndN_Solution1(n) == expected)
            printf("Solution1 passed.
    ");
        else
            printf("Solution1 failed.
    ");
    
        if (NumberOf1Between1AndN_Solution2(n) == expected)
            printf("Solution2 passed.
    ");
        else
            printf("Solution2 failed.
    ");
    
        printf("
    ");
    }
    
    void Test()
    {
        Test("Test1", 1, 1);
        Test("Test2", 5, 1);
        Test("Test3", 10, 2);
        Test("Test4", 55, 16);
        Test("Test5", 99, 20);
        Test("Test6", 10000, 4001);
        Test("Test7", 21345, 18821);
        Test("Test8", 0, 0);
    }
    
    int main(int argc, char* argv[])
    {
        Test();
        system("pause");
        return 0;
    }
  • 相关阅读:
    js中return;、return true、return false;区别
    JS跨域设置和取Cookie
    检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(转)
    IIS7中Ajax.AjaxMethod无效的原因及解决方法
    ajax 跨域的问题 用js绕过跨域
    微服务笔记
    smali语法笔记
    Go Micro 入门笔记
    介绍微服务框架Micro笔记
    JS任务队列--笔记
  • 原文地址:https://www.cnblogs.com/CJT-blog/p/10522116.html
Copyright © 2020-2023  润新知