JZ-C-32

剑指offer第三十二题:从1到n整数中1出现的次数

  1 //============================================================================
  2 // Name        : JZ-C-32.cpp
  3 // Author      : Laughing_Lz
  4 // Version     :
  5 // Copyright   : All Right Reserved
  6 // Description : 从1到n整数中1出现的次数
  7 //============================================================================
  8 
  9 #include <iostream>
 10 #include <stdio.h>
 11 #include <string.h>
 12 #include <stdlib.h>
 13 using namespace std;
 14 
 15 // ====================方法一:未考虑时间效率,时间复杂度O(n*logn)====================
 16 int NumberOf1(unsigned int n);
 17 
 18 int NumberOf1Between1AndN_Solution1(unsigned int n) {
 19     int number = 0;
 20 
 21     for (unsigned int i = 1; i <= n; ++i)
 22         number += NumberOf1(i); //对每个数字都要做除法和求余运算
 23 
 24     return number;
 25 }
 26 
 27 int NumberOf1(unsigned int n) {
 28     int number = 0;
 29     while (n) {
 30         if (n % 10 == 1)
 31             number++;
 32 
 33         n = n / 10;
 34     }
 35 
 36     return number;
 37 }
 38 
 39 // ====================方法二:将数字分为两段,如21345分为从1到1345 和 1346到21345,时间复杂度O(logn)====================
 40 int NumberOf1(const char* strN);
 41 int PowerBase10(unsigned int n);
 42 
 43 int NumberOf1Between1AndN_Solution2(int n) {
 44     if (n <= 0)
 45         return 0;
 46 
 47     char strN[50];
 48     sprintf(strN, "%d", n); //把格式化的数据写入某个字符串,这里是将整数写入strN字符数组中
 49 
 50     return NumberOf1(strN);
 51 }
 52 
 53 int NumberOf1(const char* strN) {
 54     if (!strN || *strN < '0' || *strN > '9' || *strN == '\0')
 55         return 0;
 56 
 57     int first = *strN - '0';
 58     unsigned int length = static_cast<unsigned int>(strlen(strN));
 59 
 60     if (length == 1 && first == 0)
 61         return 0;
 62 
 63     if (length == 1 && first > 0)
 64         return 1;
 65 
 66     // 假设strN是"21345"
 67     // numFirstDigit是数字10000-19999的第一个位中1的数目
 68     int numFirstDigit = 0;
 69     if (first > 1)
 70         numFirstDigit = PowerBase10(length - 1);
 71     else if (first == 1)
 72         numFirstDigit = atoi(strN + 1) + 1;    //atoi函数:将字符串转成整数
 73 
 74     // numOtherDigits是01346-21345除了第一位之外的数位中1的数目
 75     int numOtherDigits = first * (length - 1) * PowerBase10(length - 2);    //★★
 76     // numRecursive是1-1345中1的数目
 77     int numRecursive = NumberOf1(strN + 1);
 78 
 79     return numFirstDigit + numOtherDigits + numRecursive;
 80 }
 81 
 82 int PowerBase10(unsigned int n) {
 83     int result = 1;
 84     for (unsigned int i = 0; i < n; ++i)
 85         result *= 10;
 86 
 87     return result;
 88 }
 89 
 90 // ====================测试代码====================
 91 void Test(char* testName, int n, int expected) {
 92     if (testName != NULL)
 93         printf("%s begins: \n", testName);
 94 
 95     if (NumberOf1Between1AndN_Solution1(n) == expected)
 96         printf("Solution1 passed.\n");
 97     else
 98         printf("Solution1 failed.\n");
 99 
100     if (NumberOf1Between1AndN_Solution2(n) == expected)
101         printf("Solution2 passed.\n");
102     else
103         printf("Solution2 failed.\n");
104 
105     printf("\n");
106 }
107 
108 void Test() {
109     Test("Test1", 1, 1);
110     Test("Test2", 5, 1);
111     Test("Test3", 10, 2);
112     Test("Test4", 55, 16);
113     Test("Test5", 99, 20);
114     Test("Test6", 10000, 4001);
115     Test("Test7", 21345, 18821);
116     Test("Test8", 0, 0);
117 }
118 
119 int main(int argc, char** argv) {
120     Test();
121 
122     return 0;
123 }

 

转载于:https://www.cnblogs.com/Laughing-Lz/p/5604466.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值