整数中1出现的次数(从1到n整数中出现的次数)

题目描述

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

 简单的方法:对10取模求得每一位的数,时间复杂度O(nlogn)

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n <= 0) return 0;
        int sum = 0;
        while(n){
            sum += weishu(n);
            n--;
        }
        return sum;
    }
    int weishu(int n){
        int sum = 0;
        while(n){
            if(n % 10 == 1)
                sum++;
            n /= 10;
        }
        return sum;
    }
};

或者将数字转为字符串,对每一位进行判断

剑指offer的思路:利用数学规律

这里要注意的是类似100这种情况还有首位为1的情况

public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        if(n <= 0) return 0;
        String number = n+"";
        return NumberOf1("1",number,number.length());
    }
    public int NumberOf1(String startNum,String endNum,int endNumWei){
        if(endNumWei == 1)
            return 1;
        if(startNum == "1"){
            String subNum = endNum.substring(1);
            while(subNum.length()>0&&subNum.charAt(0) == '0'){
                subNum = subNum.substring(1);
            }
            if(subNum.length()==0) {
                int sumOne = 0;
                for(int i=0;i<endNum.length();i++){
                    if(endNum.charAt(i)=='1')
                        sumOne++;
                }
                endNum = (strToint(endNum)-1)+"";
                return sumOne + NumberOf1("1",endNum,endNum.length());
            }
            else
                return NumberOf1(subNum,endNum,endNumWei) +
                    NumberOf1("1",subNum,subNum.length());
        }else{
            if(endNum.charAt(0) != '1')
                return (int)(Math.pow(10.0,endNumWei-1) + ((int)endNum.charAt(0)-(int)('0')) * (endNumWei-1) * Math.pow(10.0,endNumWei-2));
            else{

                return strToint(endNum.substring(1))+1 + (endNumWei-1) * (int)Math.pow(10.0,endNumWei-2);
            }
        }
    }
    public int strToint(String str){
        int sum = 0;
        for(int i=0;i<str.length();i++)
            sum = sum * 10 + (int)(str.charAt(i)-'0');
        return sum;
    }
}

 还是没有书上的算法简洁:

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n<=0) return 0;
        char strN[50];
        sprintf(strN, "%d", n);
        return NumberOf1(strN);
    }
    int NumberOf1(char* strN){
        if(*strN <'0'||*strN>'9')
            return 0;
        unsigned int len = static_cast<unsigned int>(strlen(strN));
        int first = *strN - '0';
        if(len == 1 && first == 0)
            return 0;
        if(len == 1 && first > 0)
            return 1;
        
        //计算首位为1的个数
        int numFirstDigit = 0;
        if(first == 1)
            numFirstDigit = atoi(strN+1)+1;
        else if(first > 1)
            numFirstDigit = (int)pow(10.0, len-1);
        int otherDigits = first *(len-1)*(int)pow(10.0, len-2);
        int recurisiveDigits = NumberOf1(strN+1);
        return numFirstDigit + otherDigits + recurisiveDigits;
    }
};
原文地址:https://www.cnblogs.com/ttzz/p/13974708.html