今天你如约而至了吗?今天这道题看题目就比较有意思,很好玩,上题:
题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
分析:不知道为啥叫丑数~~以下是参考了题解中的分析和解答,感觉这个方法比较好。
什么叫丑数,其实就是除了1和它本身之外,只包含x个2,y个3,z个5(其中x,y,z为任意非负整数)。举个栗子
0不是丑数
1=2^0*3^0*5^0 x=0,y=0,z=0
2=2^1*3^0*5^0 x=1,y=0,z=0
3=2^0*3^1*5^0 x=0,y=1,z=0
5=2^0*3^0*5^1 x=0,y=0,z=1
4=2^2*3^0*5^0 x=2,y=0,z=0
6=2^1*3^1*5^0 x=1,y=1,z=0
10=2^1*3^0*5^1 x=1,y=0,z=1
为什么要这样写,其实满足丑数=丑数*(2,3,5)
例如:
1*(2,3,5)= 2,3,5
2*(2,3,5)= 4,6,10
3*(2,3,5)= 6,9,15
4*(2,3,5)= 8,12,20
5*(2,3,5)= 10,15,25
后面计算出来的数其实都是丑数,但是我们会发现出现了重复的现象,所以我们可以设置三个变量p2,p3,p5,分别表示2,3,5的次数。
每次计算之后我们只取出最小的那个,同时其对应的变量++,循环往复就得到了最终的结果。
方法一:
代码:
//import java.lang.Math; //Math是在lang包下,不需要导包
public class Solution {
public int GetUglyNumber_Solution(int index) {
if(index==0)return 0; //一定要对输入的内容进行初步的判断
int p2=0; //设置三个变量,分别表示2,3,5的个数
int p3=0;
int p5=0;
int[] list=new int[index];
list[0]=1; //提前把1放入丑数数组中
for(int i=1;i<index;i++){
list[i]=Math.min(list[p2]*2,Math.min(list[p3]*3,list[p5]*5));//选出最小的一个
if(list[i]==list[p2]*2)p2++; //当前最小的值是哪个,对应变量++;
if(list[i]==list[p3]*3)p3++;
if(list[i]==list[p5]*5)p5++;
}
return list[index-1];
}
}
牛客运行通过
运行时间:13ms
运行内存:9444Kb
这个方法还是很巧妙的,其实主要要理解一点:丑数=丑数*(2,3,5)。理解了这一点其他都是比较好想到的。
注意:一定要对出入的参数进行初步判断,无论题目中是否说明!!!!
方法二
一个数m是另一个数n的因子,是指n能被m整数,即m%n==0.根据丑数的定义,丑数只能被2,3,5整数,即:一个数能被2整数,连续除以2,一个数能被3整数,连续除以3,一个数能被5整数,连续除以5。如果最后这个数等于1,则是丑数。
代码:
public class Solution {
public int GetUglyNumber_Solution(int index) {
if(index<=0)return 0;
int ugly=1;
int number=0;
int uglycount=0;
while(uglycount<index){
number++;
if(isUgly(number)){
ugly=number;
uglycount++;
}
}
return ugly;
}
public boolean isUgly(int number){
while(number%2==0){
number/=2;
}
while(number%3==0){
number/=3;
}
while(number%3==0){
number/=3;
}
return (number==1)?true:false;
}
}
牛客上运行没有通过,超时了,但是在本地IDEA上运行用过,小伙伴们可以看一下。
方法一是牺牲空间提高时间,方法二是省了空间牺牲了时间,各有所需。
欢迎各位互相交流~~