多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 編程之美1:那些關于1的個數的經典面試題

編程之美1:那些關于1的個數的經典面試題

來源:程序員人生   發布時間:2015-04-28 08:39:46 閱讀次數:2984次

那些關于1的個數的經典面試

好長時間沒有練算法了,筆試題1做,發現非常費勁,所以近日來找來《編程之美》1書來看看練練。為了鼓勵自己多練,樓樓可能會出個專欄甚么的,感興趣的同學我們可以1起抱團,樓樓也會保證每天都會更新。那今天呢,就是《編程之美》的第1題了,原題叫做“1”的數目,樓樓會把這道題還有相干的1些題都會記錄下來,下面要開始了哦,Are you ready?

題目1 給定1個10進制正整數N,寫下從1開始,到N的所有整數,然后數1下其中出現的所有“1”的個數

  • 解法1 暴力窮舉

我相信如果是我們正在處于筆試或面試確當場,暴力窮舉肯定是我們的第1個想法。1個1個算,算出1中出現“1”的個數,再算出2中出現“1”的個數,順次類推,直到N中“1”的個數,然后相加得出最后的結論。我們看代碼:

#include <iostream> using namespace std; int getOneShowTimes(unsigned int n) ; int getOneShowSumTimes(unsigned int N) ; int main() { unsigned int N = 123; cout << "1出現的次數為:" << getOneShowSumTimes(N) << endl; system("pause"); } int getOneShowSumTimes(unsigned int N) { unsigned int count = 0; for (unsigned int i = 0; i <= N; i++) { count += getOneShowTimes(i); } return count; } int getOneShowTimes(unsigned int n) { unsigned count = 0; while(0 != n) { count += (n % 10) == 1 ? 1 : 0; n /= 10; } return count; }

我們分析1下復雜度,外層循環要循環N次,內存循環要循環log10N+1次,所以總的復雜度為O(N(log10N+1)),可以看出這個復雜度是比較高的。

下面我們想一想,有無更簡單的辦法呢?比如對1個3位數123而言,“1”只能在個位出現,或10位出現或千位出現。如果是依照這個原理來統計的,那我們可以完全將外層循環下降到log10N+1次。那我們來寫幾個例子來尋覓1下規律。

  • 解法2 逐位統計法

如123,那末

個位出現1 10位出現1 百位出現1
1 10 100
11 11 101
21 12 102
31 13 103
41 14 104
51 15
61 16
71 17
81 18
91 19
101 110
111
121 119 123
總計13次 總計20次 總計24次
料想公式N/10+1 料想公式(N/100+1)?10 料想公式(N/1000)?100+N%100+1

但是在這里有我們有幾個特殊的情況需要特別斟酌,如相應的位數為0怎樣辦?比如51和50結果是完全不1樣的。還有相應的位數為1怎樣辦?12和22的結果也是不1樣的。我下面把結果羅列出來,大家也能夠試著推導1下。

分情況 個位出現1 10位出現1 百位出現1
bit = 0 (N/10)?1 (N/100)?10 (N/1000)?100
bit = 1 (N/10)?1+N%1+1 (N/100)?10+N%10+1 (N/1000)?100+N%100+1
bit > 1 (N/10+1)?1 (N/100+1)?10 (N/1000+1)?100

總結1下,假定每位對應的權值為quan,如個位quan = 1,10位quan = 10,那末總的公式為

bit=0 bit=1 bit>1
(N/(10?quan))?quan (N/(10?quan))?quan+N%quan+1 (N/(10?quan)+1)?quan

下面看代碼:

package net.mindview.util; public class MyThread { public static void main(String[] args) { int N = 123; System.out.println("總共出現" + getOneShowTimes(N) + "次"); } public static int getOneShowTimes(int N) { int numPerBit; //存儲每位的數目 int sumTimes = 0; //存儲最后的結果 int quan = 1; //每位的權值,各位為1,10位為10,順次類推 int tempN = N; if (0 == N) { return 0; } while(0 != tempN) { numPerBit = tempN % 10; sumTimes += getOneShowTimesPerBit(N, numPerBit, quan); tempN /= 10; quan *= 10; } return sumTimes; } public static int getOneShowTimesPerBit(int N, int numPerBit, int quan) { if (0 == numPerBit) { return N / (quan * 10) * quan; } else if (1 == numPerBit) { return (N / (quan * 10)) * quan + N % quan + 1; } else { return (N / (quan * 10) + 1 ) * quan; } } }

非常不好意思,這里的代碼是Java的,由于原來就寫好了,我就懶得再寫成c++的了,請見諒哈!復雜度為O(log10N+1),可以看出來效力是提升了很多的。下面我們來看第2個題。

題目2:給定1個10進制正整數N,寫下從1開始,到N的所有整數,然后數1下其中2進制中出現的所有“1”的個數

題目1是10進制,題目2是2進制。注意這里的區分。那我們一樣寫寫看,看能不能找出甚么規律

假定N=3,那末我們看每位出現“1”的次數之和都是相等的,都是2次。那末結果就是2 * 2=4總共4次。其次,假定N=7,我們又驚奇地發現,所有小于7的數中每位出現“1”的次數之和也是相等的,每位出現“1”的次數之和為4,那末結果就是3 * 4 = 12次。那我們可以料想,當N=15時,總數為4 * 8 = 32次。這是非常理想的情況,那當N = 13呢?很easy,N=13,我們就先算N = 7。還剩下6個數,視察1下我們可以發現,剩下的6個數中“1”出現的次數=最小的6個數“1”出現的次數+6。那末我們就把問題降下來了,本來是要求左側6個數中1出現的個數,轉變成了求右側6個數中1出現的個數。

本來要求的“1”出現的個數 簡化以后要求的“1”出現的個數
1000 0000
1001 0001
1010 0010
1011 0011
1100 0100
1101 0101

那末剩下的6個數,又可以重復前面的步驟,先求N=3。
總結1下,假定不大于N的最小的2的次方數為biggest2Pow
log2(biggest2Pow)?biggest2Pow2+(N+1 生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生

------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 日韩精品亚洲一级在线观看 | 国产成人久久精品二区三区牛 | 午夜影院h | 日产精品一区二区三区免费 | 欧美欧美欧美 | 亚洲精品一区二区三区网址 | 欧美日韩高清观看一区二区 | 国产极品美女在线 | 欧美一级性生活视频 | 变态 另类 国产 亚洲 | 性欧美video 性欧美videofreel另类 | 久久就是精品 | 欧美综合国产精品日韩一 | 亚洲精品免费观看 | 成人在线一区二区 | 国产日韩欧美中文字幕 | 青娱乐伊人 | 亚洲午夜免费视频 | 被公侵犯肉体中文字幕一区二区 | 久久视频一区 | 国产a级一级久久毛片 | 日本一区二区视频 | 色综合美国色农夫网 | 日本japanesexxxx人妖2 | 亚洲国产国产综合一区首页 | 亚洲视频在线一区 | 看一级毛片一区二区三区免费 | 日韩精品久久久毛片一区二区 | 欧美3p在线观看一区二区三区 | 在线观看视频在线观看 | 日韩精品久久一区二区三区 | 久久性视频 | 国产人澡人澡澡澡人碰视频 | 日本aaaa片毛片免费观看 | 亚洲成a人v欧美综合天堂软件 | 欧美一级人与动毛片免费播放 | 久久久久无码国产精品一区 | 精品久久影院 | 亚洲区视频 | 豆国产97在线 | 欧洲 | 最近中文字幕高清中文字幕在线看 |