输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数

题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。

分析:首先最先想到的是遍历从1到n的每个数,判断每个数中包含1的个数,再相加。 时间复杂度:如果输入数字为n,n有O(logn)位,我们需要判断每个数字的每一位是不是为1,所以时间复杂度为O(n*logn)。如果输入数字很大的时候,就需要大量的计算,效率不高。

接下来观察规律:

从个位到最高位,我们判断每一位1出现的次数。比如

对于数23                    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

个位为1的数为01,11,21。次数为3

十位为1的次数,10,11,12.13 14 15 16 17 18 19  次数为10次

总结规律得到:

在个位出现1的个数=n/10+(个位=0,0;个位>1,1;个位=1,低0位+1);

十位位出现1的个数=n/100*10+(十位=0,0;十位>1,10,;十位=1,低一位+1);

百位出现1的个数=n/1000*100+(百位=0,0;百位>1,100;百位=1,低两位+1);

手工求解:

125

个位=12+1

十位=10+10

百位=0+26

59个1

算法描述:

(1)求出所给正整数a的位数,假设为N,num保存1的个数

(2)另p=a,num+=p/10i*10i-1;(i=1...N-1);

(3)令p=a/10i-1;p=p%10,if(p==1) num+=a%10i-1+1;if(p>1) num+=10i-1;(i=1....N)

(4)printf(num);

因为算法复杂度只和数字的位数有关,位数为logn位,所以总的时间复杂度为O(logn).

参考:http://www.cnblogs.com/GoAhead/archive/2012/05/28/2521415.html

输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数

时间: 2024-10-10 22:56:36

输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数的相关文章

任意输入一个正整数,求出其各位数字之和

//任意输入一个正整数,求出其各位数字之和 #include <stdio.h>void main(){    int num,s=0;     printf("请任意输入一个正整数:\n");     scanf("%d",&num);     while(num!=0)     {         s=num%10+s;//没有赋值的操作,在编写程序时没有意识到这一点         num=num/10;     } printf(&quo

输入一个字符串,求字符的所有排列

#include <iostream> #include <cstring> #include <string> using namespace std; void ComStr(char *str, string &s,int m) { if (m == 0) { cout<<s<<endl; return ; } if (*str != '\0') { s.push_back(*str); ComStr(str+1,s ,m-1);

求从1到n这n个整数的十进制表示中1出现的次数

/*-------------------------包含头文件------------------------------------*/ #include<stdio.h> #include<stdlib.h> #include<malloc.h> #include<string.h> int count=0; /*-------------------------结构体定义部分------------------------------*/ typed

输入一个正整数,求它各位数的数字之和

class Test{ public static void main(String[] args){ int iSum = 0; Scanner scan = new Scanner(System.in); System.out.print("请输入一个正整数:"); int iNum = scan.nextInt(); int iC = iNum; while(iNum % 10 == 0) iNum = iNum / 10; while(iNum % 10 > 0){ in

输入一个数组,求最小的K个数

被这道题困了好久,看了剑指Offer才知道OJ上的要求有点迷惑性. 题目: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4. 一直以为要按照顺序输出,想的方法是插入排序算法复杂度是O(N*K),当然这个地方就显得自己有点蠢了.不过我想在“按序输出”的错误题意下还没有啥更好的方法. 然后看了剑指Offer原书,原来输出不必按照顺序.所以第一种方法是快速选择.这种方法算法复杂度是O(N).不过在实际的使用中可能有点隐含的时间参数

输入一个日期,求是这一年中的第几天

有两种方法进行实现 方法一: int year,month,date;  int day;  int sum=0;  boolean flag=false;  do{  Scanner scan=new Scanner(System.in);  System.out.println("请输入年份");  year=scan.nextInt();  System.out.println("请输入月份");  month=scan.nextInt();  System.

输入一个整型数组,数组里有正数,也有负数。求所有子数组的和的最大值

题目: 输入一个整型数组,数组里有正数,也有负数. 数组中一个或连续的多个整数组成一个子数组. 求所有子数组的和的最大值.要求时间复杂度为 O(n). 解答: 1 public class Solution { 2 public static void main(String[] args) { 3 int[] arr = {1,-2,3,10,-4,7,2,-5}; 4 System.out.println(maxSub(arr)); 5 } 6 7 private static int ma

剑指Offer面试题32(java版):从1到n整数中1出现的次数

题目:输入一个整数n,求从1到n个整数的十进制表示中1出现的次数.例如输入12,从1到12这些整数中包含1的数字有1,10,11,和12,1一共出现了5次. 方法一:不考虑时间效率的解法,靠它拿到Offer有点难: 如果在面试的时候碰到这个问题,应聘者大多能想到最直观的方法,也就是累加1到n中每个整数1出现的次数.我们可疑每次通过对10求余数判断整数的个位数字是不是1.如果这个数字大于10,除以10之后再判断个位数字是不是1.基于这个思路,我们写出下面的代码: /** * 从1到n整数中1出现的

从1到整数n中1出现的次数

题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从1到12这些整数中包含1的数字有1,10,11和12共出现了5次. 不考虑时间效率的解法: 1 int NumberOf1Between1AndN(unsigned int n) 2 { 3 int number=0; 4 for(unsigned int i=1;i<=n;++i) 5 number +=NumberOf1(i); 6 return number; 7 } 8 int NumberOf1(un