寻找1的个数

一、题目与要求

  • 给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数。
  • 要求:写一个函数 f(N) ,返回1 到 N 之间出现的 “1”的个数。例如 f(12)  = 5。

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

二、设计思路

  寻找1的出现的个数,可以采用枚举的方式,统计1出现的个数,但是,这种算法效率不高,那么,在正整数中,1出现的个数是有规律的,如果能找到这个规律,效率应该会得到很大的提高。举例:

  个位 十位 百位 。。。
3 1 0 0 。。。
13 2 4 0 。。。
23 3 10 0 。。。
33 4 10 0 。。。
。。。 。。。 。。。 。。。 。。。
93 10 10 0(0*100) 。。。
103 11 10(1*10) 4((3+1)+(0*100)) 。。。
113 12 14(1*10+4) 14((13+1)+(0*100)) 。。。
123 12 20((1+1)*10) 24((23+1)+(0*100)) 。。。
203 21 20(2*10) 100((0+1)*100) 。。。
213 22 24(2*10+4) 100((0+1)*100) 。。。
223 23 30((2+1)*10) 100((0+1)*100) 。。。

由以上数据分别对十位和百位进行分析,若abc表示一个三位数,对十位进行分析,那么:

  • 若b=0,则十位为1的个数为a*10;
  • 若b=1,则十位为1的个数为a*10+c+1;
  • 若b>1,则十位为1的个数为(a+1)*10;

推广:若abcde表示任意位数的整数,对其中c位进行总结,那么:

  • 若c=0,则c位为1的个数为ab*(c位);
  • 若c=1,则c位为1的个数为ab*(c位)+de+1;
  • 若c>0,则c位为1的个数为(ab+1)*(c位);

那么,就可以根据这个规律,找到1出现的个数。

三、源代码

 1 // search1.cpp : 定义控制台应用程序的入口点。
 2 //
 3
 4 #include "stdafx.h"
 5 #include"iostream"
 6 using namespace std;
 7 int main()
 8 {
 9     int num;        //要输入的数据
10     int tag=1;        //从个位开始计算
11     int count=0;        //计数
12     int heigher,cur,less;    //定义当前位数据cur和比他高的位heigher,以及比他低的位less
13     cout<<"请输入数据:";
14     cin>>num;
15     while(num/tag!=0)
16     {
17         heigher=num/(tag*10);        //当前位的高位
18         cur=(num/tag)%10;            //当前位
19         less=num%tag;                //当前位的低位
20         switch(cur)
21         {
22         case 0:
23             count=count+heigher*tag;
24             break;
25         case 1:
26             count=count+heigher*tag+less+1;
27             break;
28         default:
29             count=count+(heigher+1)*tag;
30             break;
31         }
32         tag=tag*10;
33     }
34     cout<<"1出现的个数为:"<<count<<endl;
35     return 0;
36 }

四、实验结果

五、实验分析

  最近在看一本书,叫《你得灯亮着吗》,讲的就是应该如何正确的分析处理问题,就像这个题一样,我们很容易就会想到使用枚举的方式,并且解决方法也很简单,但是,这真的使我们想要的吗?不是,我们需要的是高效的准确的方法,虽然最简单的办法一般不会有错误,但我们大多数情况下,需要的是效率加正确性,那么如何是两者兼顾,就要探究问题的规律了。但是问题的规律不是那么容易找的,所以还是要在平时多多积累,只有好的基础,才能更好的思考问题,不然,基础都不会,又怎么去寻找更好的解决方法呢。

时间: 2024-10-04 23:36:09

寻找1的个数的相关文章

LeetCode-三数之和(排序,固定一个数,然后双指针寻找另外两个数)

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [   [-1, 0, 1],   [-1, -1, 2] ] 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/3sum 分析: 暴力法的

剑指Offer28 最小的K个数

包含了Partition函数的多种用法 以及大顶堆操作 1 /************************************************************************* 2 > File Name: 28_KLeastNumbers.cpp 3 > Author: Juntaran 4 > Mail: [email protected] 5 > Created Time: 2016年08月31日 星期三 19时45分41秒 6 *******

LeetCode15题: 寻找三数和,附完整代码

本文始发于个人公众号:TechFlow 今天介绍的算法题是LeetCode 15题,3 Sum,也成三数求和问题. Link 3Sum 难度 Medium 描述 给定一个整数的数组,要求寻找当中所有的a,b,c三个数的组合,使得三个数的和为0.注意,即使数组当中的数有重复,同一个数也只能使用一次. Given an array nums of n integers, are there elements a , b , c in nums such that a + b + c = 0? Fin

Asp.net Core中使用NLog,并封装成公共的日志方法

1.安装NLog "NLog.Extensions.Logging": "1.0.0-rtm-alpha4" 2.配置NLog public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging&quo

你真的适合做软件开发吗

前段时间一个朋友跟我说,他说做软件开发不仅累,而且从来不跟人接触,整天要对着电脑研究代码.整个人都完全脱离社会了,自己都快变成代码了. 我笑着以一个过来人的身份对他说,你现在后悔了吧?!天下没有后悔的药,若想不后悔,就必须对将来要做的事情有个了解,这就好比商人投资某个项目一样,必须做好深入的考察后,才能进入,否则就凭着一腔热情,失败在所难免. 软件开发行业曾一度被各大媒体报渲染我21世纪的昭阳产业,人才缺口达到多少多少等等.听的大家是蠢蠢欲动,摩拳擦掌恨不得卯足劲冲进去好好干一番事业.然后各种媒

数据绑定(数据源控件 -- ObjectDataSource)

数据绑定(数据源控件 -- ObjectDataSource) ObjectDataSource 在网页控件和数据访问组件间建立一个声明性的链接.ObjectDataSource 非常灵活,并可以和多种类型的组件一起工作. 要使用它,你的数据访问类必须遵守以下几个规则: 所有逻辑必须包含在单个类中(如果使用不同的类选择和更新数据,那么必须把它们封装在一个更高层的类中) 调用单个方法后,它必须提供查询结果 查询结果必须是几条记录的组合,可以表现为集合.数组.DataSet.或实现 IEnumera

Callable、Future、RunnableFuture、FutureTask的原理及应用

1. Callable.Future.RunnableFuture.FutureTask的继承关系 在多线程编程中,我们一般通过一个实现了Runnable接口的对象来创建一个线程,这个线程在内部会执行Runnable对象的run方法.如果说我们创建一个线程来完成某项工作,希望在完成以后该线程能够返回一个结果,但run方法的返回值是void类型,直接实现run方法并不可行,这时我们就要通过FutureTask类来间接实现. FutureTask实现了RunnableFuture接口,而Runnab

跨越千年的RSA算法

跨越千年的RSA算法 数论,数学中的皇冠,最纯粹的数学.早在古希腊时代,人们就开始痴迷地研究数字,沉浸于这个几乎没有任何实用价值的思维游戏中.直到计算机诞生之后,几千年来的数论研究成果突然有了实际的应用,这个过程可以说是最为激动人心的数学话题之一.最近我在<程序员>杂志上连载了<跨越千年的 RSA 算法>,但受篇幅限制,只有一万字左右的内容.其实,从数论到 RSA 算法,里面的数学之美哪里是一万字能扯完的?在写作的过程中,我查了很多资料,找到了很多漂亮的例子,也积累了很多个人的思考

2016年中国大学生程序设计竞赛(合肥)-重现赛1009 HDU 5969

最大的位或 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 18    Accepted Submission(s): 17 Problem Description B君和G君聊天的时候想到了如下的问题.给定自然数l和r ,选取2个整数x,y满足l <= x <= y <= r ,使得x|y最大.其中|表示按位或,即C. C++.