(转) 统计在从1到n的正整数中1出现的次数

转自:http://blog.csdn.net/sjf0115/article/details/8600599

问题:

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

例如:
N= 2,写下1,2。这样只出现了1个“1”。

N= 12,我们会写下1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12。这样,1的个数是5。

问题一:

写一个函数f(N),返回1到N之间出现1的个数,比如f(12)= 5。

解法一:

让我们首先想到的一个方法是:遍历1~N,统计每个数1出现的个数,相加便得到所有1的个数。

[cpp] view plaincopy

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. long long int Count(long long int n){
  5. long long int count = 0;
  6. while(n){
  7. count += (n % 10 == 1)?1:0;
  8. n = n / 10;
  9. }
  10. return count;
  11. }
  12. int main()
  13. {
  14. long long int n,i,count;
  15. while(scanf("%lld",&n) != EOF){
  16. count = 0;
  17. for(i = 1;i <= n;i++){
  18. count += Count(i);
  19. }
  20. printf("%lld\n",count);
  21. }
  22. return 0;
  23. }

这个方法虽然很容易想,但是不是一个好方法。致命问题就是效率问题。如果给定的N很大,需要很长时间才能得出计算结果。

解法二:

分析的出规律。

<1>1位数情况

这个简单,如果N = 3,那么从1到3的所有数字:1,2,3,只有个位数出现1,而且只出现一次。可以发现,N是个位数时,N >=1,那么f(N)= 1;N = 0,f(N)= 0;

<2>2位数情况

<3>3位数情况

同理分析4位数,5位数。。。。。

设N = abcde ,其中abcde分别为十进制中各位上的数字。

如果要计算百位上1出现的次数,它要受到3方面的影响:百位上的数字,百位一下(低位)上的数字,百位一上(高位)上的数字。

如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,则可以知道百位出现1的情况可能是:100~199,1100~1199,2100~2199,,.........,11100~11199,一共1200个。可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。

如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,则可以知道百位受高位影响出现的情况是:100~199,1100~1199,2100~2199,,.........,11100~11199,一共1200个。和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。但同时它还受低位影响,百位出现1的情况是:12100~12113,一共114个,等于低位数字(113)+1。

如果百位上数字大于1(2~9),则百位上出现1的情况仅由更高位决定,比如12213,则百位出现1的情况是:100~199,1100~1199,2100~2199,...........,11100~11199,12100~12199,一共有1300个,并且等于更高位数字+1(12+1)乘以当前位数(100)。

[cpp] view plaincopy

  1. /*N = abcde 百位上数字是c
  2. 仅以求百位上出现1的情况为例。
  3. */
  4. int count = 0;
  5. //百位上数字为0,百位上可能出现1的次数由更高位决定
  6. if(c == 0){
  7. //等于更高位数字(ab)* 当前位数(100)
  8. count += ab*100;
  9. }
  10. //百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响
  11. else if(c == 1){
  12. //更高位数字(ab) *  当前位数(100) + 低位数字(de)+1
  13. count += ab*100 + de + 1;
  14. }
  15. //百位上数字大于1(2~9),百位上出现1的情况仅由更高位决定
  16. else{
  17. //(更高位数字+1(ab+1))* 当前位数(100)
  18. count += (ab + 1) * 100;
  19. }

[cpp] view plaincopy

    1. #include<stdio.h>
    2. long long int Count(long long int n){
    3. //1的个数
    4. long long int count = 0;
    5. //当前位
    6. long long int Factor = 1;
    7. //低位数字
    8. long long int LowerNum = 0;
    9. //当前位数字
    10. long long int CurrNum = 0;
    11. //高位数字
    12. long long int HigherNum = 0;
    13. if(n <= 0){
    14. return 0;
    15. }
    16. while(n / Factor != 0){
    17. //低位数字
    18. LowerNum = n - (n / Factor) * Factor;
    19. //当前位数字
    20. CurrNum = (n / Factor) % 10;
    21. //高位数字
    22. HigherNum = n / (Factor * 10);
    23. //如果为0,出现1的次数由高位决定
    24. if(CurrNum == 0){
    25. //等于高位数字 * 当前位数
    26. count += HigherNum * Factor;
    27. }
    28. //如果为1,出现1的次数由高位和低位决定
    29. else if(CurrNum == 1){
    30. //高位数字 * 当前位数 + 低位数字 + 1
    31. count += HigherNum * Factor + LowerNum + 1;
    32. }
    33. //如果大于1,出现1的次数由高位决定
    34. else{
    35. //(高位数字+1)* 当前位数
    36. count += (HigherNum + 1) * Factor;
    37. }
    38. //前移一位
    39. Factor *= 10;
    40. }
    41. return count;
    42. }
    43. int main(){
    44. long long int a;
    45. while(scanf("%lld",&a) != EOF){
    46. printf("%lld\n",Count(a));
    47. }
    48. return 0;
    49. }
时间: 2024-08-26 23:40:07

(转) 统计在从1到n的正整数中1出现的次数的相关文章

统计从1到n所有正整数中1出现的次数

这是来自<编程之美>2.4中的题目,我只给出我的新方法,书上的方法这里略过不提,因为网上已经有很多解释书上的内容的博文了. 以下是分析: 我们先从最简单的数字开始分析. 0~9:个位数>=1时,1的出现次数均为1.个位数=0时,出现0次1.......................................................................① 10~99:十位数字=1时,比如17.先分析10~17中所有两位数中个位数上1的个数=1,再分析10~17所

技巧之C#统计字符串中字符出现的次数(转)

方法1.自定义类 class CharNum { private char c; private int num; public char C { get { return c; } } public int Num { get { return num; } set { num = value; } } public CharNum(char ch) { this.c = ch; this.num = 1; } } static void Main(string[] args) { /* */

N个任务掌握java系列之统计一篇文章中单词出现的次数

问题:统计一篇文章中单词出现的次数 思路: (1)将文章(一个字符串存储)按空格进行拆分(split)后,存储到一个字符串(单词)数组中. (2)定义一个Map,key是字符串类型,保存单词:value是数字类型,保存该单词出现的次数. (3)遍历(1)中得到的字符串数组,对于每一个单词,考察Map的key中是否出现过该单词,如果没出现过,map中增加一个元素,key为该单词,value为1(第一次出现): 如果,在map的key中发现了该单词,则通过key找到对应的value(单词出现的次数)

java怎么实现统计一个字符串中字符出现的次数

问题:假设字符串仅仅保护a-z 的字母,java怎么实现统计一个字符串中字符出现的次数?而且,如果压缩后的字符数不小于原始字符数,则返回. 处理逻辑:首先拆分字符串,以拆分出的字符为key,以字符出现次数为value,存入Map中. 源码如下: 1 import java.util.HashMap; 2 import java.util.Iterator; 3 import java.util.Map; 4 5 public class TestCompress { 6 7 public sta

键盘录入一个文件夹路径,统计该文件夹(包含子文件夹)中每种类型的文件及个数,注意:用文件类型(后缀名,不包含.(点),如:&quot;java&quot;,&quot;txt&quot;)作为key, 用个数作为value,放入到map集合中,遍历map集合

package cn.it.zuoye5; import java.io.File;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Scanner;import java.util.Set; /** 键盘录入一个文件夹路径,统计该文件夹(包含子文件夹)中每种类型的文件及个数,注意:用文件类型(后缀名,不包含.(点),如:"java","txt&qu

字符串中各字符出现次数的统计

要求:统计一个字符串中 各字符串出现的次数.比如 "a1a35b5" 统计出来应该是 a-2, 1-1, 3-1, b-1, 5-2. 思想一:用split方法将key字符切除,比较源字符串长度和新字符串长度,得出key字符个数. 图例: 代码: 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <

统计重1到n的正整数中1的个数

转:http://blog.csdn.net/sjf0115/article/details/8600599 问题: 给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有“1”的个数. 例如:N= 2,写下1,2.这样只出现了1个“1”. N= 12,我们会写下1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12.这样,1的个数是5. 问题一: 写一个函数f(N),返回1到N之间出现1的个数,比如f(12)= 5. 解法一: 让我们首先想到的一个方

C语言实现--&gt;&gt;对输入字符串中各类型出现次数的统计

问题描述: 编写一个程序统计输入字符串中:各个数字.空白字符.以及其他所有字符出现的次数. 代码实现: #include <stdio.h> #include <ctype.h> int main() {  int other=0;  int space=0;  int a[10]={0};  int i=0;  int ch=0;  while ((ch=getchar())!=EOF)  {   /*    //isspace库函数---判断输入字符ch是不是空,如果是,if条

shell统计文本中单词的出现次数

Ubuntu14.04 给定一个文本,统计其中单词出现的次数 # solution 1 grep与awk配合使用,写成一个sh脚本 fre.sh sh fre.sh wordfretest.txt #! /bin/bash# solution 1 if [ $# -eq 0 ] then echo "Usage:$0 args error" exit 0 fi if [ $# -ge 2 ] then echo "analyse the first file $1"