算法练习篇之:整数中1出现的个数

算法练习篇之:整数中1出现的个数

题目描述

求出1 ~ 13的整数中1出现的次数,并算出100~ 1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

解题思路

法一:依次遍历每个数,判断每个数里面是否包含1
法二:归纳法
具体讲方法二:
设定1、10、100、1000…为中间点,分别考虑个位、十位、百位上…有多少个包含1的数进行分析,目的为找出规律
根据设定的位置i(i=1、10、100…)对n进行分割,可以分为两部分,高位为a=n/i,低位为b=n%i。
举个例子i=100时:
1.百位对应的数字大于等于2,设n=71343,那么a=713,b=43。此时百位为1的次数有a/10+1=72次。72次中每次都包含0到99这100个连续的数,那么百位为1的数一共有72×100=7200次。也即 (a/10+1)×100
2.百位对应的数为1,设n=13198,那么a=131,b=98。此时百位对应的数就是1,需要分两部分考虑:
(1)对于a/10=13次百位为1(0到12),每次都包含包含0到99个连续数,那么百位为1的数一共有13×100=1300次。也即a/10×100。
(2)对于最高两位为13时,百位为1,此时百位为1所包含的数共有0到98个,即b+1个。
综上,百位对应的数为1时,百位为1的数共有a/10×100+b+1个。
3.百位对应的数为0,设n=13066,那么a=130,b=66。那么百位为1的次数为0到12,13次,即a/10,每次均包含0到99个连续数,那么满足要求的数共有12×100=1200个。也即a/10×100
规律如上,每一位都可以分为上述三种情况!!!!!
当百位对应的数为0或者大于等于2时,有(a+8)/10次包含0到99个连续数。之所以补8,是因为当百位为0,则a/10==(a+8)/10,当百位>=2补8会产生进位位,效果等同于(a/10+1)
当百位对应的数是1时,需要增加未满100的数b+1个。

代码实现

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

public class numberOf1Between1AndN {
    //求出1~n中所有数字出现1的次数
    public int numberOf1_1(int n){
        int number=0;
        for (int i=1;i<=n;i++){
            number+=numberof1(i);
        }
        return number;
    }
  
    public int numberOf1(int n){
        int number=0;
        for (int i=1;i<=n;i*=10){
            int a=n/i,b=n%i;
            number=number+(a+8)/10*i+(a%10==1?1:0)*(b+1);

        }
        return number;
    }
    public static void main(String[] args) {
        numberOf1Between1AndN test=new numberOf1Between1AndN();
        int count=test.numberOf1_1(13);
        System.out.println(count);

    }
}


class Solution {//这种更好理解
    public int countDigitOne(int n) {
        int dight=1,number=0;//位因子dight
        int high=n/10,cur=n%10,low=0;//分别为高位、当前位、低位
        while (high!=0||cur!=0){
            if (cur==0){
                number+=high*dight;
            }else if (cur==1){
                number+=high*dight+low+1;
            }else {
                number+=(high+1)*dight;
            }
            low+=cur*dight;
            cur=high%10;
            high/=10;
            dight*=10;
        }
        return number;
    }
}

总结

本题来源于面试经典教材《剑指offer》中 归属于其他类型题目。
同许多在算法道路上不断前行的人一样,不断练习,修炼自己!
如有博客中存在的疑问或者建议,可以在下方留言一起交流,感谢各位!
最后,感谢AIAS!

觉得本博客有用的客官,可以给个赞鼓励下! 嘿嘿

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 大整数的加减乘除运算是算法设计与分析的一个重要问题。对于大整数的加减乘除运算,需要设计高效的算法来处理。其,加法和减法可以采用类似于小学数学的竖式计算方法,乘法可以采用类似于小学数学的乘法计算方法,而除法则需要采用更为复杂的算法,如长除法或牛顿迭代法等。在算法设计与分析,需要考虑算法的时间复杂度和空间复杂度,以及算法的正确性和稳定性等问题。同时,还需要考虑算法的实际应用场景,如密码学、计算机图形学、计算机视觉等领域,以便选择合适的算法。 ### 回答2: 随着计算机科学和技术的不断发展,大整数计算逐渐成为计算机科学的一个重要问题。 在日常生活,我们经常需要处理大数的加减乘除,例如:财务管理、密码学、科学计算等。这些雄厚的数字往往需要通过一些算法进行高效的计算,这就需要一些针对大整数算法设计与分析。 大整数加法:大整数加法其实就是小学数学的竖式加法。我们可以先将两个大数的最低位相加,将结果的个位保存下来,然后将得到的进位加到下一位的计算,直到所有位数都加完。 大整数减法:大整数减法可以通过加上相反数来实现。具体来说,我们将被减数和减数的位数对齐,然后按位进行减法操作。需要注意的是,如果被减数小于减数,则需要借位。 大整数乘法:大整数乘法一般采用传统的乘法规则:将两个数的每一位相乘,并保持结果在正确的位上。需要注意的是,乘法可以通过使用一些技巧来加速计算,例如:Karatsuba算法和分治法。 大整数除法:大整数除法一般采用长除法或者二分法进行。长除法与小学时候学习的是一样的,通过将被除数的一位一位与除数对齐,然后逐个相除。二分法则通过不断地将除数倍增来加速计算。 总而言之,针对大整数的加减乘除运算需要使用一些高效的算法来进行计算。这些算法的设计和分析将会涉及到大量的数学原理和计算机科学的知识。同时,算法的实现也需要考虑到程序的效率和正确性。 ### 回答3: 随着计算机科学的发展,数字运算一直是算法设计和分析应该掌握的基础部分。除了基本的整数运算,对于大整数的加、减、乘、除等运算也非常重要。大整数的运算是超过计算机原始字长的整数的运算。 对于大整数的加、减、乘、除,我们需要使用不同的算法来执行。以下是针对大整数的四种运算的算法简介: 大整数加法:大整数加法的基本思路很简单:将大整数分割成同样长度的数字部分并对相应的数字部分执行加法运算。如果有进位,进位值将被带入下一位的计算。最终结果是一个大整数。 大整数减法:大整数减法比加法稍微复杂一些。常用的方法是将 位权相同的两个位数相减。如果被减数小于减数,则需要进行借位。借位意味着从高位借一位,同时在当前位减去10。如果需要多次借位,就需要连续地对更高的位进行借位操作。 大整数乘法:用笔和纸做乘法的方法是讲算术方法还原成使用乘法表,那在算法设计我们就可以使用竖式乘法。在这种方法,使用被乘数和乘数的每一位进行部分乘法计算,并将结果加起来。这种方法可以极大地降低计算量。 大整数除法:除法在大整数是最棘手的运算。可以将从左到右的数字逐位与除数相除。如果它小于除数,则将下一位的数字添加到被除数。具体的除数和被除数都需要调整,以确保它们具有相同的数字长度。最终结果是商和余数。 总之,算法设计和分析整数的加、减、乘、除是非常重要的部分。在实际项目,大整数的四种运算也经常出现。所以我们必须理解这些算法并熟练掌握它们。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值