首页 > 其他分享 >剑指 Offer 43 1~n整数中的十进制表示中1出现的次数

剑指 Offer 43 1~n整数中的十进制表示中1出现的次数

时间:2022-12-20 23:12:41浏览次数:72  
标签:count 10 cur Offer 43 次数 num 出现 十进制

剑指 Offer 43 | 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 < 231

思路:都是统计1 ~ n中各个位上1出现的次数然后相加,个位上1出现的次数 + 十位上1出现的次数 + 百位上1出现的次数+ … 。

方法一:
计算每个位数上1出现的次数时,先计算 \([0, n / 10 - 1]\) 中1出现的次数,再计算 \([n / 10, n]\) 中1出现的次数。因为 \([0, n / 10 - 1]\)中1出现的次数是有规律的:
个位上1出现的次数:
[0, 9] 1次
[0, 99] 10次
[0, 999] 100次
[0, 9999] 1000次
十位上1出现的次数:
[0, 99] 10次
[0, 999] 100次
[0, 9999] 1000次

所以当 cur = 0 时, 只需要计算 \([0, n / 10 - 1]\) 中 cur 位上1出现的次数 (这里的 n 是指最开始传入的 n;下面的代码中 n 每次循环都要除10,不是原始的 n 了)
当 cur = 1 时, 还要计算 \([n / 10, n]\) 中1出现的次数为 low + 1;
当 cur > 1 时, \([n / 10, n]\) 中1出现的次数刚好为 num;

int countDigitOne(int n) {
    //高位
    int low = 0, count = 0, cur;
    long num = 1; // 表示个位、十位、百位
    while (n != 0) {
        cur = n % 10; // 从个位开始遍历
        n /= 10; //
        count += n * num;
        if (cur == 1) count += low + 1;
        else if (cur > 1) count += num; 
        low += cur * num; // 记录遍历过的位数上的值,当 cur = 1 时,可以组成的 cur 位上为1的数有 low + 1 个。                  
        num *= 10;
    }
    return count;
}

方法二:
理解起来和方法一类似,只是求当 cur >= 1 时,计算 \([n / 10, n]\) 的部分1出现的次数的方式不同
大佬总结出来的数学公式:
\({n} \over {10^{k+1} }\) \(\times 10^k\) + min ( max ( n mod 10k+1 - 10k +1, 0), 10k)
k=0,1,2 分别表示个位、十位、百位...

int countDigitOne(int n) {
    long long num = 1;
    int count = 0;
    while (n >= num) {
        count += (n / (num * 10)) * num; // 注意:n / (num * 10) * num 不等于 n / 10
        count += min(max(n % (num * 10) - num + 1, 0LL), num); // n % (num * 10) - num 为方法一中的low
        num *= 10;
    }
    return count;
}

标签:count,10,cur,Offer,43,次数,num,出现,十进制
From: https://www.cnblogs.com/AngleLin/p/16995305.html

相关文章

  • 剑指 Offer II 003. 前 n 个数字二进制中 1 的个数
    题目内容给定一个非负整数n ,请计算0到n之间的每个数字的二进制表示中1的个数,并输出一个数组。说明:0<=n<=105解题思路1直接运用内置函数bin()和count()将......
  • 剑指offer 数字在排序数组中出现的次数(C++)
    题目描述统计一个数字在排序数组中出现的次数。代码实现classSolution{public:intGetNumberOfK(vector<int>data,intk){if(data.empty())re......
  • 剑指offer 二叉树的深度(C++)
    题目描述输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。代码实现/*structTreeNode{intval;......
  • 剑指offer 字符串的排列(C++)
    题目描述输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。输入描述:......
  • 剑指offer 二叉树的镜像(C++)
    问题描述操作给定的二叉树,将其变换为源二叉树的镜像。输入描述:二叉树的镜像定义:源二叉树8/\610/\/\57911镜像二叉树......
  • 剑指offer 题解目录(C++)
    序号题目知识点难度1​​二维数组中的查找​数组查找较难2​​替换空格​字符串较难3​​从尾到头打印链表​链表较难4​​重建二叉树​树中等5​​用两个栈实现队列......
  • 刷题笔记——1043.[编程入门]三个数字的排序
    题目1043.[编程入门]三个数字的排序代码whileTrue: try: li=list(map(int,input().strip().split())) li.sort() foriinli: print(i,end='') except......
  • 老男孩教育 | 98年0基础转行,三个月时间,收获满意Offer!
    没有好学历,也没有一技之长,该如何实现人生逆袭?其实想要逆袭成功并不是一件困难的事情,难的是走向成功的过程,无论你是否有学历、是否有一技之长,只要不敢于平庸你也可......
  • 剑指Offer——链表的环以及环的入口
    在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。例如,链表1->2->3->3->4->4->5处理后为1->2->5解题思路这个题包含两个子问......
  • SPC5777CDK3MMO3(MCU)IWR6843ARQGALPR(射频收发器)EP2AGX45CU17I5G(FPGA)
    概述:1、MPC5777CPowerArchitecture®微控制器是一款高性能多核MCU,优化用于要求先进性能、计时系统、安全性和功能性安全能力的工业和汽车控制应用。2、(IWR6843ARQGALPR)......