1~n整数中1出现的次数

一、需求

  • 输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
  • 例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
示例 1:

输入:n = 12
输出:5
示例 2:

输入:n = 13
输出:6

二、规律法1

2.1  思路分析

  1. 题目要求1~n中1出现的次数,考虑将n转换为字符串,然后统计字符1的个数,但这样会超时;
  2. 既然1不行,换一种思路,将n转换为字符串后,可以容易确定n的位数;
  3. 利用for循环,从个位开始直到最高位,计算每一位上1出现的次数并做累加,关键是如何计算每一位上1出现的次数;
  4. 假设现在n = 345[i]xx,现在i到了第三位,假设要计算该位上1出现的次数,当 i 左边的高位部分取不到345时,即只取000~344, i 右边的低位部分可任意取即有00~99,共100种,从而这种情况下必有345*100个1;
  5. 上面描述的高位部分取不到345的情况,假设现在取到了,那么又要分两种情况:①2 <= i < =9,这种情况下 i 右边的低位 部分随便取,共100种;② i == 1时,这种情况下 i 右边的低位部分不能随便取了,只能取xx + 1种情况;
  6. 把所有情况加起来就是结果。

2.2  代码实现

class Solution {
    public int countDigitOne(int n) {
        int count = 0;
        String str = ""+n;
        char[] chs = str.toCharArray();
        for(int i = 1; i <= chs.length; i++) {
            //n取不到high(假设n=345[i]xx,high指345),该部分必然成立
            int high = n/(int)Math.pow(10,i);
            count += high*(int)Math.pow(10,i-1);
            //n取到high...,根据第i位上的数分两种情况
            int digit = chs[chs.length-i] - '0';
            if(digit > 1) {
                count += (int)Math.pow(10,i-1);
            } else if(digit == 1) {
                count += n % (int)Math.pow(10,i-1) +1;
            }
        }
        return count;
    }
}

2.3  复杂度分析

  • 时间复杂度为O(N),其中N为元素n的位数;
  • 空间复杂度为O(N),初始化字符数组申请了n个空间;

三、规律法2

3.1  思路分析

  1. 上面的空间复杂度都很高,考虑将能不能不申请空间,当然是可以的;
  2. 通过设计一个方法求一个整数的第 i 位数来代替字符数组的遍历问题;

3.2  代码实现

class Solution {
    public int countDigitOne(int n) {
        int count = 0;
        String str = ""+n;
        for(int i = 1; i <= str.length(); i++) {
            //n取不到high(假设n=345[i]xx,high指345),该部分必然成立
            int high = n/(int)Math.pow(10,i);
            count += high*(int)Math.pow(10,i-1);
            //n取到high...,根据第i位上的数分两种情况
            int digit = getDigit(n,i);
            if(digit > 1) {
                count += (int)Math.pow(10,i-1);
            } else if(digit == 1) {
                count += n % (int)Math.pow(10,i-1) +1;
            }
        }
        return count;
    }
    //获取一个整数的第i位数,第1位是个位,第2位是十位,以此类推
    int getDigit(int n,int i) {
        int res = 0;;
        while(i != 0) {
            res = n % 10;
            n = n / 10;
            i--;
        }
        return res;
    }
}

3.3  复杂度分析

  • 时间复杂度为O(N^2),计算次数由N变为1+2+3+...N了,时间复杂度提高了;
  • 空间复杂度降低为O(1);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值