计算任意两个数之间1出现的次数的思维过程
来源:互联网 发布:windows gcc下载 编辑:程序博客网 时间:2024/05/16 15:33
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);
}
}
- 计算任意两个数之间1出现的次数的思维过程
- 计算任意两个数之间1出现的次数的思维过程
- 计算任意两个时间之间的秒数
- 计算两个任意日期之间的工作日
- 任意两个时间之间的星期几的次数-横
- 计算任意两个日期之间相隔的天数以及年数
- 计算二进制数中1出现的次数
- 计算数组中任意一个单词出现的次数(HashMap)
- java---计算出现次数最大的任意字符
- CI20.4--计算0~n之间某个数出现的次数
- 计算两个日期之间的周数
- Java中计算任意两个日期之间的工作天数
- 计算任意两个日期之间的天数问题
- Java中计算任意两个日期之间的工作天数
- php计算任意两个日期之间的天数
- C++ 计算任意两个日期之间的天数
- 得到两个long型数字之间的任意一个数
- SQL查出任意两个数之间的所有数字
- 一维和二维傅里叶变换的CPP代码
- jquery
- hdu 1233 最小生成树 "还是畅通工程"
- 哈夫曼树
- SSH2注入SessionFactory 空指针
- 计算任意两个数之间1出现的次数的思维过程
- [JavaScript][图形图像]图形图像动画处理利器推荐--raphael.js (付:流程设计器例子)
- C++结构体实例和类实例的初始化
- C++的显示转换
- C/C++中枚举类型(enum)的使用解惑
- 完了,来csdn这么久了,竟然不会发帖子!
- Ogre角色控制类(源码)
- Policy-based design
- sed, a stream editor