統計數字問題 演算法實現 (補0遞迴法)
在演算法的實驗課上,我們的老師給我們出了一道演算法題。
演算法問題出自《演算法設計與實驗題解》的課後練習1-1,問題描述如下:
一本書的頁碼從自然數1開始順序編碼直到自然數n。書的頁碼按照通常的習慣編排,每個頁碼都不含多餘的前導數字0。例如第6頁用6表示而不是06或006。數字統計問題要求對給定書的總頁碼,計算出書的全部頁碼中分別用到多少次數字0,1,2,3,.....9。
演算法分析:
這個演算法使用遞迴的方法來實現,具體步驟如下:
具體的演算法思想是:
說明:n為乙個自然數,
m表示為十進位制數的位數(如1234,則n為1234,m為4)。
對於乙個m位整數,我們可以把0到n之間的n+1個整數從小到大這樣來排列:
000......0
.............
099......9
100......0
100......1
.............
199......9
200......0
.............
299......9
300......0
.......... n
這樣一直排到自然數n。對於從0到199......9這個區間來說,拋去最高位的數字不看,其低m-1位恰好就是m-1個0到m-1個9共10^(m-1)個數,這時對於此區間共有(m-1)*10^(m-1)個數字(包括0~9)。利用原著中的遞推公式,在這個區間裡,每個數字出現的次數(不包括最高位數字)為(m-1)*10^(m-2)。假設n的最高位數字是x,那麼在n之間上述所說的區間共有x個。那麼每個數字出現的次數x倍就可以統計完這些區間。再看最高位數字的情況,顯然0到x-1這些數字在最高位上再現的次數為10^(m-1),因為乙個區間長度為10^(m-1)。而x在最高位上出現次數就是n%10^(m-1)+1了。接下來對n%10^(m-1)(這個數其實就是去除最高位剩下的位數),即n去掉最高位後的那個數字再繼續重複上面的方法直到個位,就可以完成題目要求了。
詳細的例子說明:
對於乙個數字34567,我們可以這樣來計算從1到34567之間所有數字中每個數字出現的次數:
從0到9999,這個區間的每個數字的出現次數可以使用原著中給出的遞推公式,即每個數字出現4000次。從10000到19999,中間除去萬位的1不算,又是乙個從0000到9999的排列,這樣的話,從0到34567之間的這樣的區間共有3個。所以從00000到29999之間除萬位外每個數字出現次數為3*4000次。然後再統計萬位數字,每個區間長度為10000,所以0,1,2在萬位上各出現10000次。而3則出現4567+1=4568次。之後,拋掉萬位數字,對於4567,再使用上面的方法計算,一直計算到個位即可。
下面是本人寫的**:
#include "stdafx.h"
#include
#include
int sum_num(int);
int count[10]=;
int main()
int sum_num(int n)
//計算最高為的數字出現的次數。
for(int j=0;j//計算在x為最高為時在最後的區間出現的次數。
count[x]+=n%(pow1)+1;
if(m0==0)
return sum_num(n%pow1)+pow1; //遞迴求解。累加每一次遞迴返回的數值並儲存到函式中。以作為減去0的個數。
統計數字問題
在王曉東編著的 演算法設計與實驗題解 中看到的這個問題,問題描述如下 一本書的頁碼從自然數1開始順序編碼直到自然數n。書的頁碼按照通常的習慣編排,每個頁碼都不含多餘的前導數字0。例如第6頁用6表示而不是06或006。數字統計問題要求對給定書的總頁碼,計算出書的全部頁碼中分別用到多少次數字0,1,2,...
統計數字問題
問題描述如下 一本書的頁碼從自然數1開始順序編碼直到自然數n。書的頁碼按照通常的習慣編排,每個頁碼都不含多餘的前導數字0。例如第6頁用6表示而不是06或006。數字統計問題要求對給定書的總頁碼,計算出書的全部頁碼中分別用到多少次數字0,1,2,3,9。演算法設計與分析習題 分析 考察由0,1,2.9...
統計數字問題
問題描述 給定乙個整數n,統計從1到n 數字最高位不允許為0 這麼多個數中0,1,2,3,4,5,6,7,8,9分別出現的次數。問題解決 採用遞迴求解統計每乙個數字0,1,2,9出現的次數累加。源 include stdafx.h include int results 10 void count ...