剑指offer-- 丑数(Java)

题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。求按从小到大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做第一个丑数。

思路:
  直观思路:从1开始逐一判断每个整数是否为丑数,直到找到第n个丑数,时间效率太低。因为对于每一个整数都要计算,即使一个整数不是丑数,也要进行除法和取余操作。
  空间换时间的解法:
  创建数组存放已经排序好的丑数,这将消耗一定的内存开销。关键是怎样确保数组里的丑数是有序的。根据丑数的定义,丑数应该是另一个丑数的2、3或者5倍的结果,因此,我们从数组中已有的丑数里找到三个丑数T2、T3、T5,它们分别和2、3、5相乘得到的值恰好比已有的最大丑数大,三个乘积中最小的一个就是下一个丑数,存放入数组中,同时更新T2、T3、T5,使它们仍然保持与2、3、5的乘积恰好比已有的最大丑数大。这种思路不需要在非丑数上进行计算,时间复杂度较低。

考点:以空间换时间

实现:

public int GetUglyNumber_Solution(int index) {
    if(index<=0) return 0;
    int[] ugly = new int[index];
    ugly[0] = 1;
    int count = 1;
    int T2 = 0;
    int T3 = 0;
    int T5 = 0;
    while(count<index){
        ugly[count++] = getMinimum(ugly[T2]*2,ugly[T3]*3,ugly[T5]*5);
        if (ugly[T2]*2==ugly[count-1])
            T2++;
        if (ugly[T3]*3==ugly[count-1])
            T3++;
        if (ugly[T5]*5==ugly[count-1])
            T5++;
    }
    return ugly[count-1];
}
private int getMinimum(int a,int b,int c){
    if(a>b)
        a=b;
    if(a>c)
        a=c;
    return a;
}

/*逐一判断每个数是否为丑数,效率太低
public int GetUglyNumber_Solution1(int index) {
    if(index<=0)return 0;
    int count = 0;
    int number = 0;
    while(count<index){
        number++;
        if(isUgly(number)){
            count++;
        }
    }
    return number;
}
public boolean isUgly(int data){
    while(data%2==0){
        data = data/2;
    }
    while(data%3==0){
        data = data/3;
    }
    while(data%5==0){
        data = data/5;
    }
    if(data == 1){
        return true;
    }else{
        return false;
    }
}

收获:

  1. 判断m是否为n的因子:即判断n能否被m整除,也就是n%m=0。要掌握判断因子的方法。例如判断丑数的程序如下:
public boolean isUgly(int data){
    while(data%2==0){
        data = data/2;
    }
    while(data%3==0){
        data = data/3;
    }
    while(data%5==0){
        data = data/5;
    }
    if(data == 1){
        return true;
    }else{
        return false;
    }
}

     2.丑数是另一个丑数的2、3或者5倍,要记住这类特性和规律。特别是在遇到类似的新概念时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值