zoukankan      html  css  js  c++  java
  • 面试题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];
    
    }
    
  • 相关阅读:
    Rotation Kinematics
    离职 mark
    PnP 问题方程怎么列?
    DSO windowed optimization 代码 (4)
    Adjoint of SE(3)
    IMU 预积分推导
    DSO windowed optimization 代码 (3)
    DSO windowed optimization 代码 (2)
    OKVIS 代码框架
    DSO windowed optimization 代码 (1)
  • 原文地址:https://www.cnblogs.com/flyingrun/p/13540070.html
Copyright © 2011-2022 走看看