牛客剑指Offer面试题43:1~n整数中1出现的次数(最优法不好想但不能放弃)

题目描述

求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

思路

1.分两部分统计:(数字分为两段,如给定21345,则分为1-1345和1346-21345两段)
(1)对于第二段(1346-21345),
第一步统计1出现在最高位的次数(判断最高位是否大于1,若大于1,则次数为10** (字符串长度-1);若最高位为1,则次数为除最高位外 后几位+1)
第二步统计1出现在最高位之外其他位的情况
(2)对于第一段(1-1345),采用按照(1)中操作递归的方法统计1的次数

注:
Str+1应该是字符数组的指针指向次高位
C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)
strlen() :计算字符串 str 的长度,直到空结束字符,但不包括空结束字符
static_cast (expr): 强制类型转换运算符
sprintf函数详解

代码

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        //检验有效性
        if(n <= 0)
            return 0;
        //书上初始化的字符数组为50位
        char strN[20];
        //将整数n转换为字符串
        sprintf(strN, "%d", n);
        return numberOf1(strN);
    }
    
    int numberOf1(const char* Str)
    {
        //检验有效性
        if(!Str || *Str < '0' || *Str >'9' ||*Str == '\0')
            return 0;
        //取首位
        int first = *Str - '0';
        //计算长度并判断数字位数
        unsigned int length = static_cast<unsigned int>(strlen(Str));
        
        //数组是否为1位(非0与否)
        if(first == 0 && length == 1)
            return 0;
        if(first > 0 && length == 1)
            return 1;
        //数字为多位
        //如21345,划分两段1-1345 和 1346-21345,先统计第二段
        //第一部分:计算1出现在最高位的情况,统计
        //声明此种情况的次数
        int numFirstDigit = 0;
        if(first > 1)
            numFirstDigit = powerBase10(length - 1);
        //首位为1
        else if(first == 1)
            numFirstDigit = atoi(Str+1) + 1;
            
        //第二部分:1出现在除最高位外其他几位的情况
        //声明一个变量记录此种情况的次数
        int numOtherDigit = first * (length - 1) * powerBase10(length - 2);
        //第三部分:统计1-1345
        //声明记录次数的变量
        int numRecursive = numberOf1(Str+1);
        
        return numFirstDigit + numOtherDigit + numRecursive;
    }
    
    //计算10的次幂
    int powerBase10(unsigned int n)
    {
        int result = 1;
        for(int i = 0; i < n;++i)
            result *= 10;
        return result;
    }
};
发布了65 篇原创文章 · 获赞 0 · 访问量 2040

猜你喜欢

转载自blog.csdn.net/ljmiiianng/article/details/103792739