ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

丑数

2021-04-11 13:59:12  阅读:279  来源: 互联网

标签:丑数 return pUglyNumbers int number 乘以


题目描述:

给你一个整数 n ,请你找出并返回第 n 个 丑数 。
丑数 就是只包含质因数 2、3 和 / 或 5 的正整数。

示例 1:

输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。

示例 2:

输入:n = 1
输出:1
解释:1 通常被视为丑数。

需要考虑到的测试用例:

  • 功能测试: 输入 2、 3、 4、 5、 6 等;
  • 特殊输入测试: 边界值1、无效输入0
  • 性能测试:输入较大的数字,如 1500

解法1: 暴力破解,逐个判断每个整数是不是丑数

所谓一个数 m 是另一个数 n 的因子,是指 n 能被 m 整除,也就是n % m == 0。根据丑数的定义,丑数只能被2 、 3 和 5 整除。也就是说,如果一个数能被 2 整除,那就连续除以 2; 如果一个数能被 3 整除,那就连续除以 3;如果一个数能被 5 整除,那就连续除以 5。如果最后得到的是 1,那么这个数就是丑数,否则不是。
根据分析可以写出如下判断丑数的代码:

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(int index){
	if(index < 0) {return 0;}
	
	int number = 0;
	int uglyFound = 0;
	while(uglyFound < index) {
		++number;
		
		if(IsUgly(number)) {
			++uglyFound;
		}
	}
	return number;
}

但是该解法效率不足,最大的问题是每个整数都需要计算。

解法2:创建数组保存已经找到的丑数,用空间换时间

前面算法之所以效率低吗,是因为不管一个数是不是丑数,我们都要对它做计算。所以要试着找一种只要计算丑数的方法,而不在非丑数的整数上花费时间。根据丑数的定义,丑数应该是另一个丑数乘以2、 3 或者 5 的结果(1 除外)。因此可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数乘以2、 3 或者 5 得到的。

这种思路的关键在于怎样确保数组里面的丑数是排好序的。假设数组中已有若干个丑数排好序存放在数组中,并且把已有最大的丑数记作 M,接下来分析如何生成下一个丑数。该丑数肯定是前面某一个丑数乘以2、 3 或者 5 的结果,所以首先考虑把已有的每个丑数乘以 2 的结果,在乘以 2 的时候,能得到若干个小于或者等于 M 的结果,因为是按照顺序排序的,所以小于或等于 M 的结果肯定已经在数组中了,不需要再次考虑。此外还会得到若干个大于 M 的结果,但我们只需要第一个大于 M 的结果,因为我们希望丑数是从小到大的顺序生成的,其他更大的结果以后再说。我们把得到的第一个乘以 2 后大于 M 的结果记为 M2,同理,第一个乘以 3 后大于 M 的结果记为 M3,第一个乘以 5 后大于 M 的结果记为 M5,那么下一个丑数应该是 M2、 M3、 M5 这三个数中最小者。

前面分析的时候,提到把已有的每个丑数分别乘以 2、 3、 5,事实上这不是必须的,因为已有的丑数是按照顺序存放在数组中的。对乘以 2 而言,肯定会存在某一个丑数 T2,排在它之前的每个丑数乘以 2 的结果肯定都会小于已有的最大丑数,在它之后的每个丑数乘以 2 的结果都会太大。只需要记下这个丑数的位置,同时每次生成新丑数的时候都会去更新这个T2。对乘以 3 和 5 而言,也存在同样的 T3 和 T5。

有了如上分析,可以写出如下代码:

class Solution {
public:
    /**
    * @brief: found the ugly
    * @return[int]: ugly
    * @param n[int]: index 
    **/
    int nthUglyNumber(int n) {
        if(n < 0){
            return 0;
        }

        int *pUglyNumbers = new int[n];
        pUglyNumbers[0] = 1;
        int nextUglyIndex = 1;

        int *pMultiply2 = pUglyNumbers;
        int *pMultiply3 = pUglyNumbers;
        int *pMultiply5 = pUglyNumbers;

        while(nextUglyIndex < n){
            int min = Min(*pMultiply2 * 2, *pMultiply3 * 3, *pMultiply5 * 5);
            pUglyNumbers[nextUglyIndex] = min;

            while(*pMultiply2 * 2 <= pUglyNumbers[nextUglyIndex]){
                ++pMultiply2;
            }
            while(*pMultiply3 * 3 <= pUglyNumbers[nextUglyIndex]){
                ++pMultiply3;
            }
            while(*pMultiply5 * 5 <= pUglyNumbers[nextUglyIndex]){
                ++pMultiply5;
            }

            ++nextUglyIndex;
        }

        int ugly = pUglyNumbers[nextUglyIndex - 1];
        delete[] pUglyNumbers;
        return ugly;
    }

    /**
    * @brief: find the minimum number in 3 numbers
    * @return[int]: minimum number
    * @param numner1, number2, number3[int]: numbers to compare
    **/
    int Min(int number1, int number2, int number3){
        int min = (number1 < number2) ? number1 : number2;
        min =(min < number3) ? min : number3;
        return min;
    }
};

标签:丑数,return,pUglyNumbers,int,number,乘以
来源: https://blog.csdn.net/xuesuoziluoshu/article/details/115596559

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有