题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路
1.首先是怎么判断一个数是丑数?
如果能被2整除,那就让它连续除以2,直到不能再除了,
如果能被3整除,那就让它连续除以3,直到不能再除了
如果能被5整除,那就让它连续除以5,直到不能再除了
如果最后结果是1的话,那它就是一个丑数,否则就不是
public boolean isUgly(int num) {
if(num < 1)
return false;
if(num == 1)
return true;
while(num % 2 == 0){
num /= 2;
}
while(num % 3 == 0){
num /= 3;
}
while(num % 5 == 0){
num /= 5;
}
return num == 1? true:false;
}
那么就进行遍历数字,直到找到第N个丑数
public class Solution {
public int GetUglyNumber_Solution(int index) {
if(index < 1)
return 0;
int digit = 0;
int i = 0;
while(i < index){
digit++;
if(isUgly(digit)){
i++;
}
}
return digit;
}
public boolean isUgly(int num) {
if(num < 1)
return false;
if(num == 1)
return true;
while(num % 2 == 0){
num /= 2;
}
while(num % 3 == 0){
num /= 3;
}
while(num % 5 == 0){
num /= 5;
}
return num == 1? true:false;
}
}
但是最后的结果是超时的,500 / 596 个通过测试用例,后面的数字是超时的
分析一下,效率较低的原因,对于每一个数都要去判断是否是丑数,不管之前是否已经判断过了,例如1400,判断1400的时候,1400/2 =700,那么要接着对700进行判断,700其实之前已经判断过是否为丑数了。无法对这些已知信息进行再利用,所以效率就很低。
因此,来看下一个方法
2.不去考虑非丑数,就是使用2,3,5来生成丑数,并且将丑数按序放在数组里面。
class Solution {
public int nthUglyNumber(int n) {
//用数组来存储所有的丑数,保持顺序就好
//由于丑数都是*2 *3 *5得来的,所以维持三指针
int[] dp = new int[n];
dp[0] = 1;
int i2 = 0,i3 = 0,i5 = 0;
for(int i = 1;i < n;i++){
int min = Math.min(dp[i2]*2,Math.min(dp[i3]*3,dp[i5]*5));
if(min == dp[i2]*2) i2++;
if(min == dp[i3]*3) i3++;//不能改成else if,因为使用if可以避免重复的情况,比如2*3和3*2
if(min == dp[i5]*5) i5++;
dp[i] = min;
}
return dp[n-1];
}
}
来源:CSDN
作者:fsdgfsf
链接:https://blog.csdn.net/fsdgfsf/article/details/103909445