計算任意兩個數之間1出現的次數的思維過程

 

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);
}
}
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章