现在的位置: 首页 > 综合 > 正文

求1到N的数中1出现的个数

2012年12月01日 ⁄ 综合 ⁄ 共 1375字 ⁄ 字号 评论关闭

方法1:将从1到N的所有数枚举出来,每个数都计算一下出现了多少个1,最后相加就可以得到结果,复杂度是O(n*lnn)

方法2:通过每一个位上1出现的次数来计算总的出现次数,举例来说512,

各位出现1的数包括:

1 (1)

11, 21,31,..91  (9)

101,121,131,...191(10)

201,211,221...291(10)

301,311,321,...391(10)

401,411,421,...491(10)

501,511, (2)

各位贡献的是52个,(51+1)*1 

十位贡献的1的个数为:

10, 11 ,12,....19(10)

110,111,...119 (10)

210, 211...219(10)

310,311,...319(10)

410,411,...419(10)

510, 511,512

(5)*10 + 2 +1

百位贡献的1的个数为:

100,,199 (100)

(0+1)*100

经过不断的这么分析,可以发现一个规律:

如果p位为0,那么该位贡献的结果为高位的数*10^p;

如果p为为1,那么该位贡献的结果为高位的数字*10^p + 低位数字 +1

如果p位为大于1,那么该位贡献的结果为(高位数字+1)*10^p

这个算法只和输入数字的长度有关系,输入数字的的长度为lnN,因此复杂度为lnN

依据上面的分析编写程序如下:

#include <stdio.h>
int Count1(int value) {
  int num = 0;
  while (value) {
    if (value % 10 ==1) {
      num++;
    }
    value = value / 10;
  }
  return num;
}
int Power(int radix, int exp) {
  int result = 1;
  for (int i = 0; i < exp; ++i) {
    result *= radix;
  }
  return result;
}
int Count1_1(int value) {
  int current_number = 0;
  int higher_parts = 0;
  int lower_parts = 0;
  int radix = 1;
  int num = 0;
  while (value / radix) {
    current_number = (value / radix) % 10;
    lower_parts = value - (value / radix) * radix;
    higher_parts = value / (radix * 10);
    switch (current_number) {
      case 0:
        num += higher_parts * radix ;
        break;
      case 1:
        num += higher_parts * radix  + lower_parts + 1;
        break;
      default:
        num += (higher_parts + 1) * radix ;
    }
    radix *= 10;
  }
  return num;
}  
  
int main(int argc, char** argv) {
  const int kValue = 512;
  int num = 0;
  for (int i = 0; i <= kValue; ++i) {
    num += Count1(i);
  }
  printf("%d\n", num);
  printf("%d\n", Count1_1(kValue));
}

参考文献:

http://www.nowamagic.net/algorithm/algorithm_CountOccurrencesOfOne.php

编程之美 2.4

抱歉!评论已关闭.