• 【LeetCode-数学】1~n整数中1出现的次数


    题目描述

    输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

    例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

    示例:

    输入:n = 12
    输出:5
    
    输入:n = 13
    输出:6
    

    说明:
    1 <= n < 2^31
    题目链接: https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/

    思路

    由于 n 的范围非常大,所以暴力求解是行不通的。

    假设 n 是 x 位数,第 i 位表示为 (n_i),所以 (n=n_xn_{x-1}dots n_1)。我们从第 i 位 (n_i) 将 n 分为两个部分:

    • (n_xn_{x-1}dots n_{i+1}) 被称为高位 high;
    • (n_{i-1}n_{i-2}dots n_1) 被称为地位 low;
    • (n_i) 被称为当前位 cur;
    • (10^i) 称为位因子,记为 digit;

    high、low、cur、digit 的初始化为:

    int high = n/10;
    int low = 0;
    int cur = n%10;
    long digit = 1; // long 类型,否则会溢出
    

    high、low、cur、digit 的更新方法为:

    low += cur*digit;
    cur = high%10;
    high /= 10;
    digit *= 10;
    

    在每一步,我们根据 high、low、cur、digit 的情况来计算 1 的个数 ans,具体分 3 种情况:

    • cur==0,此时 ans += high*digit;
    • cur==1,此时 ans += hight*digit+low+1;
    • cur==2~9 的情况,ans += (high+)*digit;

    这篇题解举了几个例子来介绍为什么要这么做。

    代码如下:

    class Solution {
    public:
        int countDigitOne(int n) {
            int high = n/10;
            int low = 0;
            int cur = n%10;
            long digit = 1;  // long 类型,否则会溢出
            int ans = 0;
            while(high!=0 || cur!=0){  // 注意条件
                if(cur==0) ans += high*digit;
                else if(cur==1) ans += high*digit+low+1;
                else ans += (high+1)*digit;
    
                low += cur*digit;
                cur = high%10;
                high /= 10;
                digit *= 10;
            }
            return ans;
        }
    };
    
    • 时间复杂度:O(logn)
    • 空间复杂度:O(1)

    参考

    https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/

  • 相关阅读:
    UVA 1386 Cellular Automaton
    ZOJ 3331 Process the Tasks
    CodeForces 650B Image Preview
    CodeForces 650A Watchmen
    CodeForces 651B Beautiful Paintings
    CodeForces 651A Joysticks
    HUST 1601 Shepherd
    HUST 1602 Substring
    HUST 1600 Lucky Numbers
    POJ 3991 Seinfeld
  • 原文地址:https://www.cnblogs.com/flix/p/13378496.html
Copyright © 2020-2023  润新知