面試題49:醜數
阿新 • • 發佈:2020-08-21
把只包含質因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,但14不是,因為它包含質因子7。 習慣上我們把1當做是第一個醜數。求按從小到大的順序的第N個醜數。
解題思路
- 暴力列舉法(會超時,一般的C++程式執行10^9次就會超過1s而超時)
- 空間換時間,儲存已計算的醜數,並通過已計算的醜數預測未來的醜數
上程式碼(C++香)
法一:暴力列舉法(超時)
#define maxN 10010 #define maxNN 0xFFFFFFF // 判斷是否是素數 bool isPrime(int num){ // 1不是素數 if(num < 2) return false; // 2是素數,不會執行for for(int i = 2; i < num; i++){ if(!(num % i)) return false; } return true; } // 先求出一部分素數,陣列下標為素數標記 void primeCache(int num[]){ for(int i = 0; i <= maxN; i++){ if(isPrime(i)) num[i] = 1; } } // 先求出一部分素數,陣列值為素數標記 void primeCachePlus(int num[]){ int m = 0; for(int i = 2; i <= maxN; i++){ if(isPrime(i)) num[m++] = i; } } bool isUglyNum(int prime[], int num){ if(num <= 1) return true; if(num % 2 != 0 && num % 3 != 0 && num % 5 != 0) return false; for(int i = 3; prime[i] <= num; i++){ // 不為0 if(!(num % prime[i])) return false; } return true; } int GetUglyNumber_Solution(int index) { // 得到素數快取 int num[maxN]; memset(num, -1, sizeof(num)); primeCachePlus(num); // 找到所有的醜數 int m = 0; for(int i = 1; i <= maxNN; i++){ if(isUglyNum(num, i)){ m++; if(m == index) return i; } } }
法二:暴力列舉法(超時,但這樣的做法更妙)
bool isUgly(int number){ while(number % 2 == 0) number /= 2; while(number % 3 == 0) number /= 3; while(number % 5 == 0) number /= 5; return (number == 1) ? true : false; } // 這樣也會超時 int GetUglyNumber_SolutionPlus(int index) { int number = 0; int uglyFound = 0; while(uglyFound < index){ number++; if(isUgly(number)) uglyFound++; } return number; }
法三:空間換時間,儲存已計算的醜數,並通過已計算的醜數預測未來的醜數(AC)
int myMin(int number1, int number2,int number3){ int min = (number1 < number2) ? number1 : number2; return (min < number3) ? min : number3; } int GetUglyNumber_Solution(int index) { if(index <= 0) return 0; int pUglyNumbers[index]; memset(pUglyNumbers, -1, sizeof(pUglyNumbers)); pUglyNumbers[0]= 1; int nextUglyIndex = 1; int* pMultiply2 = pUglyNumbers; int* pMultiply3 = pUglyNumbers; int* pMultiply5 = pUglyNumbers; while(nextUglyIndex < index){ // 求出當前最大的醜數 pUglyNumbers[nextUglyIndex] = myMin(*pMultiply2 * 2, *pMultiply3 * 3, * pMultiply5 * 5); // 更新M2 while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex]) pMultiply2++; while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex]) pMultiply3++; while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex]) pMultiply5++; nextUglyIndex++; } return pUglyNumbers[index - 1]; }