標籤:number
題目描述:http://ac.jobdu.com/problem.php?pid=1214
把只包含因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,但14不是,因為它包含因子7。
習慣上我們把1當做是第一個醜數。求按從小到大的順序的第N個醜數。
解析:
醜數的定義應該為:質因子只含有2、3、5的數 。1 預設是一個醜數。
e.g. 8 = 2*2*2; 18 = 2*3*3 都是醜數
直觀想法是:
判斷一個數是否是醜數,如果它能被2整除,則一直除以2,同理能被3,5整除,一直除以3,5;如果最後的結果為 1,則是醜數。
bool IsUgly(int num) { while (num % 2 == 0) num /= 2; while (num % 3 == 0) num /= 3; while (num % 5 == 0) num /= 5; if (num == 1) return true; return false;}
但是如果逐個從小到大,找出第1500個醜數,必須對第1500個醜數之前的所有數進行上述計算,演算法不夠高效。
第二種思路:
避免逐個判斷一個數是否是醜數,而是直接通過計算得到醜數。
根據定義,醜數的質因子只有2/3/5,所以一個初始的醜數 1,通過1次或多次乘以 2,3,5 可以得到任意醜數。
如何找出第n個醜數 ?
需要使用輔助數組空間儲存n個醜數;
對於一個已經有序的醜數數組,設最大值為M,對於數組中的元素分別乘以2,3,5,則大於M且最小的那個數,即為下一個醜數。
為了避免每次從數組開始乘以因子後判斷是否大於M,我們應該記錄乘以2/3/5後將大於M的數,使得下一次 因子乘以2/3/5後能直接大於已存在的最大丑數
#include <iostream>#include <algorithm>using namespace std;int GetUglyNumber(const int &index) { int* uglyNums = new int [index]; uglyNums[0] = 1; int* pMulti2 = uglyNums; int* pMulti3 = uglyNums; int* pMulti5 = uglyNums; int nextIndex = 1; while (nextIndex < index) { // 大於現有最大丑數的最小數,作為下一個醜數 uglyNums[nextIndex] = min(*pMulti2 * 2, min(*pMulti3 * 3, *pMulti5 * 5)); // 後移2的因子索引,使得下一次 pMulti2 * 2 直接大於已存在的最大丑數 while (*pMulti2 * 2 <= uglyNums[nextIndex]) pMulti2++; while (*pMulti3 * 3 <= uglyNums[nextIndex]) pMulti3++; while (*pMulti5 * 5 <= uglyNums[nextIndex]) pMulti5++; nextIndex++; } int result = uglyNums[index-1]; delete uglyNums; return result;}int main() { int index = 1500; cout << GetUglyNumber(index) << endl; cout << GetUglyNumber(11) << endl;}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
34 - 醜數