每日一道算法题-寻找丑数
?
題目:我們把只包含因子2、3和5的數(shù)稱作丑數(shù)(Ugly Number)。例如6、8都是丑數(shù),但14不是,因為它包含因子7。習慣上我們把1當做是第一個丑數(shù)。求按從小到大的順序的第1500個丑數(shù)。
分析:尋找一個數(shù)是不是滿足某種數(shù)(質(zhì)數(shù),水仙數(shù))等,最簡單的方法就是遍歷,對于任意一個丑數(shù)必定可以寫成2^m*3^n*5^p,因而對于一個丑數(shù),只含有2,3,5因子,也就意味著該數(shù)number%2==0;number%3==0;number%5==0,如果一個數(shù)能被2整除,我們就連續(xù)除以2;能被3整除,我們就連續(xù)除以3;能被5整除,我們就連續(xù)除以5;如果最后得到1,則該數(shù)是素數(shù),否則是丑數(shù)。
?
上面計算中主要的不足在于,逐一遍歷,這樣對于不是丑數(shù)的數(shù)的判斷會造成大量的時間浪費,如果能夠根據(jù)已經(jīng)計算好的丑數(shù),計算出下一個丑數(shù)就可以避免這種情況,實現(xiàn)從丑數(shù)到丑數(shù)的高效算法,根據(jù)定義可知,后面的丑數(shù)肯定是前面已知丑數(shù)乘以2,3,5得到的。
我們假設一個數(shù)組中已經(jīng)有若干丑數(shù),并且這些丑數(shù)是按順序排列的,我們把現(xiàn)有的最大丑數(shù)記為max,則下一個丑數(shù)肯定是前面丑數(shù)乘以2,3,5得到的。不妨考慮乘以2得到的情況,我們把數(shù)組中的每一個數(shù)都乘以2,由于原數(shù)組是有序的,因為乘以2后也是有序遞增的,這樣必然存在一個數(shù)M2,它前面的每一個數(shù)都是小于等于max,而包括M2在內(nèi)的后面的數(shù)都是大于max的,因為我們還是要保持遞增順序,所以我們?nèi)〉谝粋€大于max的數(shù)M2。同理對于乘以3的情況,可以取第一個大于max的數(shù)M3,對于乘以5的情況,可以取第一個大于max的數(shù)M5。
最終下一個丑數(shù)取:min{M2,M3,M5}即可。
int?GetUglyNumber_Solution2(int?index)
{
????if(index <= 0)
????????return?0;
?
????int?*pUglyNumbers =?new?int[index];
????pUglyNumbers[0] = 1;
????int?nextUglyIndex = 1;
?
????int?*pMultiply2 = pUglyNumbers;
????int?*pMultiply3 = pUglyNumbers;
????int?*pMultiply5 = pUglyNumbers;
?
????while(nextUglyIndex < index)
????{
????????int?min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
????????pUglyNumbers[nextUglyIndex] = min;
?
????????while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex])
????????????++pMultiply2;
????????while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex])
????????????++pMultiply3;
????????while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex])
????????????++pMultiply5;
?
????????++nextUglyIndex;
????}
?
????int?ugly = pUglyNumbers[nextUglyIndex - 1];
????delete[] pUglyNumbers;
????return?ugly;
}
?
int?Min(int?number1,?int?number2,?int?number3)
{
????int?min = (number1 < number2) ? number1 : number2;
????min = (min < number3) ? min : number3;
?
????return?min;
}
第二種方法由于不需要在非丑數(shù)的整數(shù)花費時間,因而時間復雜度要小很多,在vc6+win7的平臺上,index=1500時,方法1的運行時間為40s,方法2的時間是1s;然而方法2需要動態(tài)分配內(nèi)存,占用空間,而方法2則沒有這樣的內(nèi)存開銷。說白了,第二種方法是用空間換時間
?
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰(zhàn)指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。總結
以上是生活随笔為你收集整理的每日一道算法题-寻找丑数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows使用opencv训练模型过
- 下一篇: JAVA运行时异常及检查式异常