剑指offer-第5章优化时间和空间效率(丑数)

题目:我们把只包含因子2,3,5的数叫做丑数。寻找第1500个丑数。通常把1当成第一个丑数。

思路1:第一步判断是否为丑数:丑数是只包含2,3,5的数,因此一定可以被2,3,5整除。通过求余数是否为零做为判断条件,通过除以来减小整个数的值,知道整个数为1.返回true.

第二步找到第N个丑数的值,这一种做法的缺点是,不是丑数的数也要求余数除数的运算,因此耗时。因此我们提出一种以空间换时间的方法(谁让如今硬件更新的快呢)。如2思路。

思路2:我采用一个数组按照从小到大的顺序存放丑数。数组中最后一个放入的丑数即是最大的丑数M。然后,将M之前的数分别乘以,2,3,5来找到下一个大于M的丑数。改变M的值为最后找的的丑数。在2乘以M之前的丑数的时候一定存在某个丑数在它之前的数和2相乘都小于M,之后的数都大于M。我们可以记录下这个数。并且更新它。就可以很快的找到和2相乘大于M的那个丑数了。

Java代码思路1:

//思路:第一步:判断一个数是否为丑数。由于丑数是只包好2,3,5的因子的数,因此我们自然就想到了判断一个丑数先对2进行求余数如果为0再对它进行求除数减小数的大小,
//同样对3,和5也一样,最后如果结果为1就返回true。第二步,通过判断是否为丑数来数出第N个丑数对应的值。
public class FindUglyNumber {
    //判断一个数是不是丑数
    public boolean isUgly(int number){
        if(number<=0)
            return false;
        while(number%2==0)
            number/=2;
        while(number%3==0)
            number/=3;
        while(number%5==0)
            number/=5;
        return (number==1)?true:false;
    }
    public int uglyNumber(int uglyNumber){
        if(uglyNumber<=0)
            return 0;
        int ugly=0;//记录丑数的个数
        int number=0;//记录数字
        while(ugly<uglyNumber){
            number++;
            if(isUgly(number))
                ugly++;
        }
        return number;
    }
    public static void main(String[] args){
        FindUglyNumber findUglyNumber=new FindUglyNumber();
        int uglyNumber=findUglyNumber.uglyNumber(3);
        System.out.println(uglyNumber);
    }

}

Java代码思路2:

//思路:将uglyNumber按照从小到大的顺序保存在数组中。因为uglyNumber是只包含2,3,5因子的数,
//因此可以用一个M表示数组中最大的数,也是数组中最后一个存入的数,而将之前的丑数分别乘2,3,5,然后保留大于M值的最小数。
//作为下一个M。我们前面说,M之前的每一个丑数都乘以2,3,5,其实这个可以确定在乘以2时在一定存在某个值,在它之前的数都小于M
//在它之后的数都大于M。
public class FindUglyNumber1 {
   public int findUglyNumer(int index){
       int[] uglyNumber=new int[index];
       uglyNumber[0]=1;
       int nextNumber=1;
       int nextNumber2=0;
       int nextNumber3=0;
       int nextNumber5=0;
       while(nextNumber<index){
           int min=min(uglyNumber[nextNumber2]*2,uglyNumber[nextNumber3]*3,uglyNumber[nextNumber5]*5);
           uglyNumber[nextNumber]=min;
           while(uglyNumber[nextNumber2]*2<=uglyNumber[nextNumber])
               nextNumber2++;
           while(uglyNumber[nextNumber3]*3<=uglyNumber[nextNumber])
               nextNumber3++;
           while(uglyNumber[nextNumber5]*5<=uglyNumber[nextNumber])
               nextNumber5++;
           nextNumber++;
       }
       int ugly=uglyNumber[nextNumber-1];
       return ugly;
   }

public int min(int i, int j, int k) {
    int min=i<j?i:j;
    return min<k?min:k;
}
public static void main(String[] args){
    FindUglyNumber1 findUglyNumber=new FindUglyNumber1();
    int uglyNumber=findUglyNumber.findUglyNumer(3);
    System.out.println(uglyNumber);
}

}

 

转载于:https://www.cnblogs.com/hupp/p/4758071.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值