一. 题目
给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数。
要求: 写一个函数 f(N) ,返回1 到 N 之间出现的 “1”的个数。例如 f(12) = 5。
在32位整数范围内,满足条件的“f(N) =N”的最大的N是多少。
二. 设计思想
对于一个正整数,比如22133。依次计算个位、十位、百位、千位。。,然后相加。计算的过程是:个位3出现1的次数是1。十位3中1出现的次数受前面位数和后面位数影响,
他出现1个次数为(十位数字3+1)*个位数字1出现次数+(十位前面的数字221+1)*1.接下来就是依次类推。因为正整数的位数不是已知,所以我采用了WHILE循环。在循环中重点考虑的是这个数字是不是1,分两类考虑。别的就没什么了,正常敲代码就可以
三. 源代码
import java.util.Scanner; public class onetime { /** * @param args */ static int sunmer(int n){ int sum=0; int factor=1; int n2=n; int remainder=0; while(n2>0) { int num=(n2+9)/10; int true_num; if(n2%10==1) { true_num=(num-1)*factor+remainder+1; } else { true_num=num*factor; } sum+=true_num; n2/=10; factor*=10; remainder=n%factor; } return sum; } public static void main(String[] args) { // TODO Auto-generated method stub System.out.print("请输入一个正整数: "); Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int sum=sunmer(n); System.out.println("从一到该整数中‘1’出现的次数为:"); System.out.println(sum); System.out.println("在32位整数范围内,满足条件的‘f(N) =N‘的最大的N是:"); for(int i=2147483647;i>0;i--) { int sum1; sum1=sunmer(i); if(sum1==i){ System.out.println(i); break; } } } }
四. 运行结果
五.总结
刚开始我的想法不是这样的,把一个数6537,看成6000/500/30/7。几个阶段进行计算。关于这种算法重复的问题,我是这么想的,先从1算到6000,这是第一个阶段。其次是500。其实求得是6001--6500之间出现的“1”的个数,因为千位上没有1,所以省略。接下来依次类推。但是没有考虑到的问题是如果是1560.这就需要另外考虑了,如果每一位都要考虑1。代码将变得臃肿,远远不如上述的办法简单。所以最终我采用了这个办法。通过这次编程,我认识到你自己所认为最简单的方法不一定是最简单的。
时间: 2024-10-23 09:29:36