【pro2】力扣233.数字1的个数

题目链接

题目描述

给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。

示例 1:

输入:n = 13
输出:6

示例 2:

输入:n = 0
输出:0

提示:
0 <= n <= 10^9

笔记

(1)若运算数中有double或float,则其他类型数均转换为double型;

(2)若运算数中最长类型为long,则其他类型数均转换为long型;

(2)若运算数中最长类型为int,则char型也转换为int型。算术转换是在运算过程中自动完成的。

思路及代码

给定数n=abcde,假设为m位。求小于等于n的非负整数中数字1的个数,即分别统计小于等于abcde的所有整数的个位(右数第一位)、十位、百位、…、右数第m位数字中数字1的个数,最后计算它们的和即可,下以计算百位数中数字1的个数为例:

假定百位数字为1,则要满足0<=_ _ 1 _ _<=abcde,问题转化为求满足该不等式的数_ _ 1 _ _的取值种数

分三种情况讨论:

  • 当c大于1,数“1”前的值可取[0,ab],数“1”后的值可取[0,99],有(ab+1)*100种情况;

  • 当c等于1, 数“1”前的值可取[0,ab],数“1”后的值需分情况讨论:

    • 若数“1”前的值为[0,ab),则数“1”后的值可取[0,99]
    • 若数“1”前的值为ab,则数“1”后的值可取[0,de]

    故有ab*100+1*(de+1)种情况;

  • 当c小于1(即c=0),数"1"前的值可取[0,ab),数“1”后的值可取[0,99],有ab*100种情况。

上述种数之和即为所求,也即百位数中数字1的个数。

其余位数情况类似。

计算模拟题:
语言:C++

class Solution {
public:
    int countDigitOne(int n) {
        int ans=0;
        long long value=1;  //当前数所在位置 后可取值的最大种数。初始当前数为个位,只有一种情况,故value为1
        //例如当前数为百位时,其后取值范围最大为[0,99],故value=100
        int suffix=0;   //c后的数,即de
        while(n){
            int temp=n%10;  //取出当前位置的数,相当于c
            int prefix=n/10;    //c前的数,即ab
            if(temp>1){
                ans+=(prefix+1)*value;  //(ab+1)*100
            }
            else if(temp==1){
                ans+=prefix*value+(suffix+1);   //ab*100+1*(de+1)
            }
            else{   //temp<1
                ans+=prefix*value;  //ab*100
            }
            suffix+=temp*value;
            value*=10;
            n/=10;
        }
        return ans;
    }
};

遇到的问题

第一次使用int value;运行报错,原因是未考虑value*=10的数值溢出问题(n最大可达109,可进行10次while循环,value最大可达1010,超出int的109),将value的int型改为long long型即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值