45、数字1的个数

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

示例:

输入: 13
输出: 6
解释: 数字 1 出现在以下数字中: 1, 10, 11, 12, 13 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-digit-one
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

剑指offer上的思路有点复杂,没看懂…
思路:
看看这个思路
添加链接描述
此题可以分解为分别计算各位上出现1的次数的和,那么各位上出现1的次数应该如何计算呢
我们拿2104举例,在我们分别计算各位1出现的次数时,我们将数字分为preNum,curNum,sufNum。
1.计算千位出现1的次数:
preNumber = 0
curNumber = 2
sufNumber = 104
此时curNumber > 1,那么当千位为1时,即1****,可能出现1的次数有1000次(1000->1999)。此时preNumber = 0,不能借位所以只有这一种情况出现。即千位出现1的次数为1000

2.计算百位出现1的次数:
preNumber = 2
curNumber = 1
sufNumber = 4
此时curNumber = 1,那么当百位为1时,即1**,可能出现是次数又是多少呢?
我们发现现在preNumber = 2,此时百位可向前面借位
那么在不借位的情况下即21**可能会出现的情况为(2100->2104),次数就是sufNumber + 1 即4 + 1 = 5
当向前面借位时就可能出现的情况为(*100->*199),我们发现每借位一次就有100中情况,总共有preNumber * 100中情况
不借位加上借位的情况出现的次数就是(4 + 1)+ 2 * 100 = 205

3.计算十位出现1的次数
preNumber = 21
currentNumber = 0
sufNumber = 4
此时curNumber < 1,若此时十位要出现1,肯定需要向前面借位,每次借位出现1的情况为(**10->**19),也就是10
总共出现的1情况就是,preNumber * 10 = 21 * 10 = 210

4.计算个位出现1的次数
preNumber = 210
curNumber = 4
sufNumber = 0
此时curNumber又是>1,而且可向前借位,在不借位的情况下,各位1出现的次数为(2101)只有一次,
在借位的情况下为(***1)只有一种,可借位210次
总共出现1的情况为1 + 210 * 1 = 211

全部位加起来为1000 + 205 + 210 + 211 = 1626

可总结出公式为:
num为位数,即千位时num = 1000
sum为当前位数出现1的次数
当curNumber > 1 时:
sum = num + num * preNumber
当curNumber = 1 时:
sum = sufNumber + 1 + num * preNumber
当curNumber < 1 时:
sum = num * preNumber

class Solution {
    public int countDigitOne(int n) {
        if(n < 0){
            return 0;
        }
     String string = Integer.toString(n);
//        从高位到低位依次进行
        int len = string.length() - 1;
        int result = 0;
        for (int i = 0; i < string.length(); i++) {
            String tem = string.substring(0,i);
            int pre = 0;
            int cur = Integer.valueOf(string.substring(i,i + 1));
            int last = 0;
            String substring = string.substring(i + 1);
            if(substring.length() != 0){
                last = Integer.valueOf(substring);
            }
            if(tem.length() != 0){
                pre = Integer.valueOf(tem);
            }
            result += (pre) * Math.pow(10,len - i);
            if(cur > 1){
                result += Math.pow(10,len - i);
            }else if(cur == 1){
                result += last;
                result ++;
            }            
        }
        return result;

    }
   
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值