• 面试题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];
    
    }
    
  • 相关阅读:
    第一次冲刺结果演示 一组评审总结
    检查博客情况
    第十次站立会议
    第九次站立会议
    暑期实训day4
    暑期实训day3
    暑期实训day2.1——一发空格引发的血案
    暑期实训day2
    暑期实训day1
    黑板模式
  • 原文地址:https://www.cnblogs.com/flyingrun/p/13540070.html
Copyright © 2020-2023  润新知