zoukankan      html  css  js  c++  java
  • 【转载】剑指 Offer 43. 1~n整数中1出现的次数

    题目链接

    题解来自

    本题主要是找规律。暴力算法会超时。
    我们先来看一个简单的规律:
    设f(n)是只从0到n位数的最大值一共有多少个1,
    f(1) = 计算0~9有多少个1 = 1;
    f(2) = 计算0~99有多少个1;

    我们先把1开头的十位数单独拿出来考虑且只考虑十位数上1的个数:10~19共有10个1;
    然后再考虑个位数上1的个数,此时十位数范围从0~9,每种十位数对应1个个数均为f(1);
    综合得f(2) = 10 + 10 * f(1) = 20;
    同理 f(3) = 计算0~999有多少个1

    先把1开头的百位数单独拿出来考虑,且只考虑百位数:100~199,共100个1;
    再考虑其他位数上1的个数,此时百位数范围从0~9,每种百位数对应1个数均为f(2);
    综合得 f(3) = 100 + 10 * f(2) = 300;
    针对题目中数字最大为2^31次方,最多只有10位数。所以综上所述我们可以列出f(n)
    f(1) = 1;
    f(2) = 20;
    f(3) = 300;
    f(4) = 4000;
    f(5) = 50000;
    f(6) = 600000;
    f(7) = 7000000;
    f(8) = 80000000;
    f(9) = 900000000;
    f(10) = ‭10,000,000,000‬;

    针对随便一个数如2345,如何计算其包含的1的个数。
    同理规律中的计算:

    首先考虑千位数 即0345~2345共多少个1
    只考虑千位数:1000~1999:共1000个
    除了千位数后续其他位数:2 * f(3) = 600个
    考虑百位数及其后续位数 即0045~0345 共有多少个1
    只考虑百位数:100~199 :100个
    除了百位后续其他位:3 * f(2) = 60个
    考虑十位及其后续位数,即0005~0045共有多少个1
    只考虑十位:10~19:共 10个
    十位后的其他位:4 * f(1) = 4个
    最后考虑个位:0000~0005共有多少个1
    如果个位不为0,则有1个
    如果个位为0 则有0个
    共1600 + 160 + 14 + 1 = 1775
    好,有了上述步骤后,因为上述步骤没有出现某一位<=1 ,我们还需考虑如果某一位<=1是怎样的情况,
    如1045:
    在考虑千位数时,只考虑千位数的结果就不是1000了,而是1000~1045,共46个
    同时在考虑百位数值,只考虑百位数的结果就不是100了,而是000~000,共0个

    首先考虑千位数 即0045~1045共多少个1
    只考虑千位数:1000~1045:共46个
    除了千位数后续其他位数:1 * f(3) = 300个
    考虑百位数及其后续位数 即0045~0045 共有多少个1
    只考虑百位数:000~000 :0个
    除了百位后续其他位:0 * f(2) = 0个
    考虑十位及其后续位数,即0005~0045共有多少个1
    只考虑十位:10~19:共 10个
    十位后的其他位:4 * f(1) = 4个
    最后考虑个位:0000~0005共有多少个1
    *如果个位不为0,则有1个
    *如果个位为0 则有0个
    共:346 + 0 + 14 + 1 = 361个

    作者:indere-3
    链接:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/zhao-gui-lu-jie-fa-shuang-100-by-indere-3/
    来源:力扣(LeetCode)

    int countDigitOne(int n){
    	int record[] = {0, 1, 20, 300, 4000, 50000, 600000, 7000000, 80000000, 900000000};
        int count = 0;
        int res = 0;
        long flag = 1;
        int tmp = n;
        while(tmp != 0){
           int num = tmp % 10;
           tmp /= 10;
           res = res + record[count] * num;
           if(num > 1){
               res += flag;
           }else if(num == 1){
               res += n % flag + 1;
           }
           count++;
           flag *= 10;
        }
        return res;
    }
    
  • 相关阅读:
    Codeforces 689A Mike and Cellphone
    栈的一些基本操作
    Intersecting Lines POJ 1269
    Segments POJ 3304 直线与线段是否相交
    Toy Storage POJ 2398
    CF471D MUH and Cube Walls
    P 3396 哈希冲突 根号分治
    P1445 [Violet]樱花
    P6810 「MCOI-02」Convex Hull 凸包
    P3455 [POI2007]ZAP-Queries
  • 原文地址:https://www.cnblogs.com/bears9/p/13734915.html
Copyright © 2011-2022 走看看