剑指offer 从1到n整数中1出现的次数(超详细解释)

剑指offer 从1到n整数中1出现的次数

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

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

样例
输入: 12
输出: 5

思路:求整数累加每一位上1出现的次数。核心问题转变为确定一位上1出现的次数。

情况分为三类:

  1. 当前位值为0
  2. 当前位值为1
  3. 当前位值大于1

例子: 130141

我们将针对这一串中第三个数0,第四个数1,第五个数4分别讨论当前位上1出现的次数,这三个数已经包括了上述三种情况。我们将给定数的左边定义为left,右边为right。

对于 第三位数0

当left为0-12时第三位取1,right可以取任意0-999可以保证组合出来的数在合理范围内,但left=13时right没有办法取到1(不然就超了)所以在对于第三位来说1出现的次数即为left*10^(size-i-1)

对于 第四位数1

当left为0-129时第四位取1,right可以取任意0-999可以保证组合出来的数在合理范围内,但left=130时right没有办法取到大于42(不然就超了)所以在对于第四位来说1出现的次数即为left*10^(size-i-1)+right+1;

对于 第五位数4

当left为0-1301时第五位取1,right可以取任意0-999可以保证组合出来的数在合理范围内,所以在对于第五位来说1出现的次数即为(left+1)*10^(size-i-1);

所有的数不会逃出0,1,大于1三种情况因此我们只需要遍历每一位,累加相应的出现1的次数即可。

class Solution {
public:
    int numberOf1Between1AndN_Solution(int n) {
        if(!n)return 0;
        vector<int>v;
        int res=0;
        while(n){
            v.push_back(n%10);
            n/=10;
        }
        reverse(v.begin(),v.end());
        for(int i=0;i<v.size();i++){
            int left = 0,right=0;
            int t =pow(10,v.size()-1-i);
            for(int j=0;j<i;j++)left=left*10+v[j];
            for(int j=i+1;j<v.size();j++)right=right*10+v[j];
            res+=left*t;
            //等于1的情况
            if(v[i]==1)res+=right+1;
            //大于1的情况
            else if(v[i]>1)res+=t;
        }
        return res;
    }
    
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值