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

Posted Flix

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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/



以上是关于LeetCode-数学1~n整数中1出现的次数的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer 43. 1~n 整数中 1 出现的次数(数学推算,Java)

剑指 Offer 43. 1~n 整数中 1 出现的次数

LeetCode(剑指 Offer)- 43. 1~n 整数中 1 出现的次数

LeetCode(剑指 Offer)- 43. 1~n 整数中 1 出现的次数

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

面试题43. 1~n整数中1出现的次数