软件工程课堂练习——找出1-n中1出现的个数

题目:给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数。

要求:写一个函数 f(N) ,返回1 到 N 之间出现的 “1”的个数。例如 f(12)  = 5。

   在32位整数范围内,满足条件的“f(N) =N”的最大的N是多少。

一、设计思想

  通过归纳法,可以发现:

  假设N = abcde,这里a,b,c,d,e分别是十进制数N的各个数位上的数字。如果要计算百位上出现1的次数,将受3方面因素影响:百位上的数字,百位以下(低位)的数字,百位(更高位)以上的数字。

  如果百位上的数字为0,则可以知道百位上可能出现1的次数由更高位决定,比如12 013,则可以知道百位出现1的情况可能是100-199,1 100-1 199,……,11 100-11 199,一共有1 200个。也就是由更高位数字(12) 决定,并且等于更高位数字(12)×当前位数(100)。

  如果百位上的数字为1,则可以知道,百位上可能出现1的次数不仅受更高位影响,还受低位影响,也就是由更高位和低位共同决定。例如12 113, 受更高位影响,百位出现1的情况是100-199,1 100-1 199,……,11 100-11 199,一共有1 200个,和上面第一种情况一样,等于更高位数字(12)×当前位数(100)。但它还受低位影响,百位出现1的情况是12 100-12 113,一共114个,等于低位数字(113)+1。

  如果百位上数字大于1(即为2-9),则百位上可能出现1的次数也仅由更高位决定,比如12 213,则百位出现1的情况是:100-199,1 100-1 199,……,11 100-11 199,12 100-12 199,共1300个,并且等于更高位数字+1(12+1)×当前位数(100)。

二、源代码

 1 package com.java.lianxi;
 2
 3 import java.util.Scanner;
 4
 5 public class lianxi9 {
 6     public static void main(String[] args)
 7     {
 8         Scanner cin=new Scanner(System.in);
 9         System.out.print("请输入正整数的最大值:");
10         int n=cin.nextInt();
11         System.out.print("1的个数为:"+Sum1s(n));
12     }
13     public static int Sum1s( int n )
14     {
15         int iCount = 0;
16         int iFactor = 1;
17
18         int iLowerNum = 0;
19         int iCurrNum = 0;
20         int iHigherNum = 0;
21
22         while( n / iFactor != 0 )
23         {
24             iLowerNum = n - ( n / iFactor ) * iFactor;
25             iCurrNum = (n / iFactor ) % 10;
26             iHigherNum = n / ( iFactor *10 );
27
28             switch( iCurrNum )
29             {
30             case 0:
31                 iCount += iHigherNum * iFactor;
32                 break;
33             case 1:
34                 iCount += iHigherNum * iFactor + iLowerNum + 1;
35                 break;
36             default:
37                 iCount += ( iHigherNum + 1 ) * iFactor;
38                 break;
39             }
40
41             iFactor *= 10;
42         }
43         return iCount;
44     }
45 }

三、运行结果截图

四、心得体会

  这次练习的思想,和数学中的归纳法很像,俗话说就是找规律,通过列出不同情况,发现规律,从而得到了解决办法,这是一种由特殊到一般的思想。

时间: 2024-10-07 05:22:41

软件工程课堂练习——找出1-n中1出现的个数的相关文章

找出排序数组中重复数字的个数

开始我的思路是先二分查找找到一个,然后再两边分别看个数. 但是这种方法会退化到O(n).效率不好. 所以更好的方法是,先找出第一个,再找出最后一个.这个在二分查找的时候,通过判断条件的处理,是能够获得的. 比较基本的思路是,如果找到的数=k,那么判断前面一个数是不是k,如果不是,停止查找,这个是第一个:如果是的,那么继续在前半部分查找.领悟.

软件工程课堂练习--找出“水王”

一.题目要求 现有一个灌水论坛,信息学院的学生都喜欢在上面交流灌水.传说在论坛上有一个“水王”,它不但喜欢发帖,还会回复其他ID发的每个帖子.坊间风闻该“水王”发帖数目已超过了帖子数目的一半. 如果你有一张当前论坛的帖子(包括回帖)列表,其中帖子的作者ID在其中,请设计算法快速找到这个传说中的“水王”. 二.设计思路 程序的设计思路大体就是,首先设2个变量,将第一个数暂时给shuiwang这个变量并且和下一个数比较,如果相同则用一个X变量自加一,不同则减一:如此循环,如果遇到不同时,一直减减减,

Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Frist实现数据访问管理. 本例,我们模拟一个N层场景,用单独的客户端(控制台应用)来调用单独的基于REST服务的Web网站(WEB API应用) . 注意:每层使用单独的Visual Studio 解决方案, 这样更方便配置.调试和模拟一个N层应用. 假设有一个如Figure 9-3所示的旅行社和预订

程序员面试100题之十:快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值(转)

能否快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值,为了简化起见,我们假设这个数组中肯定存在至少一组符合要求的解. 假如有如下的两个数组,如图所示: 5,6,1,4,7,9,8 给定Sum= 10 1,5,6,7,8,9 给定Sum= 10 分析与解法 这个题目不是很难,也很容易理解.但是要得出高效率的解法,还是需要一番思考的. 解法一 一个直接的解法就是穷举:从数组中任意取出两个数字,计算两者之和是否为给定的数字. 显然其时间复杂度为N(N-1)/2即O(N^2).这个算法很简

算法题:找出一个数组中依次最大的k个元素

package arithmetic; import java.util.Arrays; /** * 找出一个数组中依次最大的k个元素 * @author SHI */ public class FindMaxFigure { public static void main(String[] args) { int[] a=new int[]{1,5,-1,8,0,2}; System.out.println(Arrays.toString(findBigFigure(a, 3))); } /*

delphi程序向另一个可执行程序发消息(使用GetForegroundWindow; 找出当前操作系统中活动的第一个窗口)

function FindWindowThroughWindowText(WindowText: string): THandle;var  hCurrentWindow: THandle;  cnt: Integer;  WindowTitle: array [0 .. 254] of Char;begin  Result := INVALID_HANDLE_VALUE; // 返回值预设为无效的句柄  hCurrentWindow := GetForegroundWindow; // 找出当

找出十进制数中出现的''一''的个数

一.题目要求: 给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数. 要求: 1.写一个函数 f(N) ,返回1 到 N 之间出现的“1”的个数.例如 f(12)  = 5. 2.在32位整数范围内,满足条件的“f(N) =N”的最大的N是多少. 二.解决思路 通过列举几个数进行计算,可以发现函数f(N)规律如下: 1.一位十进制数:当N>=1时,f(N)=1:当N=0时,f(N)= 0; 2.两位十进制数:f(13)=个位出现1的个数+十位出现1的个数=2+4

算法题:找出同一个序列中的最大值和最小值

package arithmetic; /** * 同时找出一个序列中最大值和最小值 * 分两种情况:(1)序列只有两个元素 * (2)序列有多个元素,有多个元素分别从序列的两端开始查找 * @author SHI */ public class MaxAndMin { public static void main(String[] args) { int[] a = { 122, 41, 4, 5, 7, 2, 89, 122, 34, 56 }; int low = 0; int high

找出一个字符串中最长重复次数的子字符串,并计算其重复次数

原题 找出一个字符串中最长重复次数的子字符串,并计算其重复次数.例如:字符串"abc fghi bc kl abcd lkm abcdefg",并返回"abcd"和2. 我的思路 为了方便表述,我们使用变量src作为原字符串,sub_str作为子字符串. 由于题目要求寻找至少重复2次的最长的子字符串,重点在于最长的子字符串,而不在于重复的最多次数.因此我们可以从长度最长的字符串入手,计算其重复次数.只要重复达到2次,即可返回该字符串. 显然长度最长的子字符串就是原串