剑指offer丑数

今天你如约而至了吗?今天这道题看题目就比较有意思,很好玩,上题:

题目描述
把只包含质因子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上运行用过,小伙伴们可以看一下。
方法一是牺牲空间提高时间,方法二是省了空间牺牲了时间,各有所需。
欢迎各位互相交流~~

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值