面试题49:丑数

把只包含质因子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];

}
原文地址:https://www.cnblogs.com/flyingrun/p/13540070.html