1.把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路1:最简单的思路,从1到大数,每个数都检测一遍是否是丑数。一个数一个数的判断,如果能被2整除,就一直除以2,如果能被3整除,就一直除以3,如果能被5整除,就一直除以5。如果最后的商为1,则说明为丑数。
static boolean isUgly(long m){ while(m%2==0){ m/=2; } while(m%3==0){ m/=3; } while(m%5==0){ m/=5; } return m==1?true:false; }
思路2:思路1的时间复杂度很高,因为每一个数都要判断(不是丑数的也要进行运算)。现在考虑以空间换时间,注意到:一个丑数的2、3、5倍也一定是丑数,而1是丑数,所以可以根据1来推出所有的丑数。
先用1乘以2、3、5,所得的数中的最小值作为第二个丑数,再用1、2分别乘以2、3、5,所得的数中的最小值作为第三个丑数。以此内推。
package com.bili.hello; import java.util.*; public class Main{ public static void main(String[] args){ System.out.println(GetUglyNumber(14)); } public static int GetUglyNumber(int index) { //边界判断 if (index <= 0) { return 0; } //定义一个数组用于存放丑数 int[] uglyNumbers = new int[index]; uglyNumbers[0] = 1; int nextUglyIndex = 1; int multiply2 = 0; int multiply3 = 0; int multiply5 = 0; int min = 0; while (nextUglyIndex < index) { min = Min(uglyNumbers[multiply2] * 2, uglyNumbers[multiply3] * 3, uglyNumbers[multiply5] * 5); uglyNumbers[nextUglyIndex] = min; while (uglyNumbers[multiply2] * 2 <= uglyNumbers[nextUglyIndex]) { multiply2++; } while (uglyNumbers[multiply3] * 3 <= uglyNumbers[nextUglyIndex]) { multiply3++; } while (uglyNumbers[multiply5] * 5 <= uglyNumbers[nextUglyIndex]) { multiply5++; } nextUglyIndex++; } int result = uglyNumbers[index - 1]; uglyNumbers = null; return result; } private static int Min(int num1, int num2, int num3) { //比较三个数中的最小数 int min = num1 < num2 ? num1 : num2; min = min < num3 ? min : num3; return min; } }
时间: 2024-10-14 16:21:32