1、我刚开始没有什么思路,仅仅是想到了将一个数字拆开成单个的数字,然后求一出现的次数,结果发现很难实现

2、没有思路,只能使用穷举法

穷举法c语言代码:

#include <iostream>

using namespace std;

const int N=1;

int main()

{

int a,b;

while (cin>>a>>b, a||b)

{ int cnt=0;

if (a>b) { int t=a; a=b; b=t; }

for (int i=a;i<=b;++i) {

int t=i;

do

{

if (t%10==N) cnt++;

t/=10;

} while (t);

}

cout<<cnt<<endl;

}

}

3、经过运行后,发现规律:凡是0到只含有9的数字,那么一的个数可以有公式:

设只含9的数字的位数为n,则有个数=n*(10的n-1次方)

4、经过思考,问题可以划分为先求从0到这任意的两个数直接含有一的次数,再求差的为题;这时,问题就转变为求从0到任意数之间含有一的个数的问题。

5、经过在稿纸上的演绎,发现拆分任意一个数得到最高位不为9,其它位都为9的数字时,开始数字只有可能是0,或者开始数字最高位与结尾数字最高位相等;这就得到了递归问题缩小规模时的相似性

6、又经过观察发现:求从0到任一个数字有如下递归表达式:

(1)当此函数的开始数字为0,结尾数字仅含9时,则有个数=n*(10的n-1次方)

(2)当此函数的开始数字为0,结尾数字为一位数时,可以直接求(只要不是0,都返回1)

(3)这是关键的一点:当开始数字最高位和结尾数字最高位相等时

a、如果此最高位不是1,那么此时的问题可以转化为求解开始数字为0,结尾数字为结尾数字除去最高位的数字之间含有1的次数的问题

b、如果次最高为是1,应该在a的基础上再加上最高位1出现的次数,即结尾数字除去最高位的数字再加一(注意这里,刚开始我出错了,误以为各个位只能是从0到此数字,其实,应该是现在这种算法)

(4)其它情况,直接拆成两个区间:例如0到1234,拆成0~999和1000~到1234

7、此时问题已经解决了大半,即已经求得了从0到任意两个数字之间的出现1的次数;但是这是不能简简单单的相减就行,主要还要加上起始数字中出现1的个数

这里附上java代码:

import java.util.Scanner;

public class NumberOfOnes {
private int getNine(int number)// 此方法计算特殊情况(即当所有位为9时的情况)
{
int n = String.valueOf(number).length();
int result = (int) (n * Math.pow(10, n - 1));
return result;
}

private boolean isNine(int number)// 判断number是否是一个所有位全为9的数字
{
String str = String.valueOf(number);
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) != '9') {
return false;
}
}
return true;
}

private int getSpecial(int number)// 此方法计算一位数字时的情况
{
if (number == 0) {
return 0;
} else {
return 1;
}
}

private int getBig(int number)// 当两个数首位相等,且为1时,计算1出现的次数
{
int n = deviceFirst(number) + 1;
return n;
}

private int deviceFirst(int number)// 获取去掉首位的数字
{
int newNumber = number
% (int) Math.pow(10, String.valueOf(number).length() - 1);
return newNumber;
}

private int[] getDevicedNumber(int number) {
int[] array = new int[2];
char[] str = String.valueOf(number).toCharArray();
str[0]--;
for (int i = 1; i < str.length; i++) {
str[i] = '9';
}
String s = String.valueOf(str);
array[0] = Integer.parseInt(s);
array[1] = array[0] + 1;
return array;
}

private int getNumberOfOne(int begin, int end)// 初次调用只能以零开始
{
if (begin == 0 && String.valueOf(end).length() == 1)// end是一位数时
{
return getSpecial(end);
}

if (begin == 0 && isNine(end))// end全为9的情况
{
return getNine(end);
}

String num1 = String.valueOf(begin);
String num2 = String.valueOf(end);
if (num1.charAt(0) == num2.charAt(0))// begin和end首位相等的情况
{
if (num1.charAt(0) == '1')// 最大位都为1
{
return getBig(end) + getNumberOfOne(0, deviceFirst(end));
} else// 最大位都不为1
{
return getNumberOfOne(0, deviceFirst(end));
}
}

int[] array = getDevicedNumber(end);// 其它情况
return getNumberOfOne(0, array[0]) + getNumberOfOne(array[1], end);
}

private int getNowNumber(int number) {
String str = String.valueOf(number);
int n = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '1') {
n++;
}
}
return n;
}

public void getNumberOfOneMain() {
Scanner reader = new Scanner(System.in);
int begin = reader.nextInt();
int end = reader.nextInt();
int result = getNumberOfOne(0, end) - getNumberOfOne(0, begin)
+ getNowNumber(begin);
System.out.println(result);
}
}

转载于:https://blog.51cto.com/wydwords/802779

计算任意两个数之间1出现的次数的思维过程相关推荐

  1. T-SQL 2 Tips: 1.计算任意两日期之间的周一到周日分别各有几个! 2.根据出生日期计算精确年龄!...

    这两个小技巧,不写不知道,一写吓一跳! 都是看似简单,实际做起来就懵,得仔细想一想,才能写对! 凡是有日期运算的程序都要细心哦! 先说第二个: 2.根据出生日期精确计算年龄!   所谓计算精确年龄就是 ...

  2. 利用函数求任意两个数之间的和

    利用函数求任意两个数之间的和 <!DOCTYPE html> <html lang="en"><head><meta charset=&q ...

  3. 两个向量之间的夹角公式_Python 计算任意两向量之间的夹角方法

    如图所示,我们要计算任意两个向量之间的夹角. (图中的坐标数字是估计值,随手给定) python代码如下 import math AB = [1,-3,5,-1] CD = [4,1,4.5,4.5] ...

  4. Java 计算任意两天之间相隔的天数

    在学习了Java中的Date类相关的方法之后,我试着自己写了小程序可以计算任意两天之间相隔的天数,挺好用的. 设计思路: 运用Date类中提供的getTime()方法,获取输入的日期与1990-01- ...

  5. Python 计算任意两向量之间的夹角

    如图所示,我们要计算任意两个向量之间的夹角. (图中的坐标数字是估计值,随手给定) python代码如下 import math AB = [1,-3,5,-1] CD = [4,1,4.5,4.5] ...

  6. JavaScript-84:利用函数求任意两个数的和

    1 利用函数求任意两个数的和 function getSum (num, num1) {console.log(num + num1); } getSum(1, 2); getSum(1100, 30 ...

  7. JS学习之求带参函数求任意两个数和

    <!DOCTYPE html> <html><head><meta charset="utf-8"><title>带参函 ...

  8. js编写一个函数,计算任意两个数字之间所能组成的奇数个数,数字必须是个位数。...

    编写一个函数,计算任意两个数字之间所能组成的奇数个数,数字必须是个位数. <body><input type="text" id="txt"& ...

  9. js 编写一个函数,计算任意两个数字之间所能组成的奇数个数

    <!DOCTYPE html> <html> <head><title></title> </head> <body> ...

最新文章

  1. 独家 | 教你使用Keras on Google Colab(免费GPU)微调深度神经网络
  2. Exchange 2010向外网发邮件的配置
  3. 基于Selenium2与Python自动化测试环境搭建
  4. sklearn中各算法类的fit,fit_transform和transform函数
  5. 通过lseek产生空洞文件
  6. CV与IP:基础,经典以及最近发展
  7. php怎样下载网上的文件,php怎样实现文件下载
  8. Unknown entity (Hibernate的findById方法参数必须加上包名)
  9. matlab 整数规划 非线性,非线性整数规划matlab
  10. lc用U盘更新固件_索尼X9000H/X9100H系列机型更新HDMI2.1固件
  11. java drag_[Java教程]一步一步理解拖拽Drag(四)
  12. 如何用计算机环境设计,计算机绘图软件在环境艺术设计中运用.doc
  13. 一叶知秋:“安全“的野指针、 static函数、成员函数、this 指针、gcc编译器、name mangling...
  14. PPmoney基于Kubernetes的DevOps实践
  15. 15个常用excel函数公式_【Excel公式函数】一大波常用的日期公式来袭,强烈建议收藏!...
  16. Java遍历包中所有类包括jar包(完整转载)
  17. java枚举类构造方法默认是,枚举类型的构造方法_Java语言程
  18. Java小白入门200例79之Java类的封装
  19. 【培训】渔网模式识别项目-算法培训-王博士
  20. Scrum Gathering开放分享:敏捷开发早期估算by火星人陈勇,北京,6.30!

热门文章

  1. System BIOS设置
  2. 数据库事务转载基础二:oracle事务隔离级别
  3. java服务限流_Java实现系统限流
  4. Canal数据同步策略
  5. Nginx的http块自定义服务日志
  6. 带你从源码了解SpringBoot启动流程
  7. 索引使用原则-联合索引最左匹配
  8. 阿里云docker hub
  9. 多案分库分表带来的问题-分布式事务
  10. MyBatis 源码解读-loadCustomLogImpl(settings)