丑数

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

思路1:硬算

  对每一个数字都循环判断,是否能被2,3,5整除为1。如果是,那就是丑数;如果不是,那就不是丑数。

  这种方法由于过于硬核,所以,时间复杂度比较大,而且牛客网是通不过的。优化的思路就是牺牲一定的空间,存储之前算好的丑数,然后用已有的丑数推导出之后的丑数。

public class Solution {
    public int GetUglyNumber_Solution1(int index) {
        if (index <= 0) {
            return 0;
        }
        int num = 0;
        int count = 0;
        while (count < index){
            num++;
            if (isUgly(num)) {
                count ++;
            }
        }
        return num;
    }
    private boolean isUgly(int num){
        while(num % 2 == 0)
            num /= 2;
        while(num % 3 == 0)
            num /= 3;
        while(num % 5 == 0)
            num /= 5;
        return num == 1 ? true : false;
    }
}

思路2: 推导法

  由丑数的定义可以知道,第M个丑数是由前M - 1个丑数中的某一个数 *2, *3, *5 得来的。比如对于丑数数组 [1, 2, 3, 4, 5, 6, 8] , 2 = 1 * 2 , 3 = 1 * 3, 4 = 1 * 2 * 2, 5 = 1 * 5, 。。。

  所以,只要我们记录第1 个丑数,然后对它进行 * 2, *3, *5 操作,然后比较取结果最小的那个,就是第二个丑数;然后对第 2 个丑数进行 * 2, *3, *5 的操作,比较结果取最小的那个,就是第三个丑数,以此类推,直到找到第 n 个丑数,就找到了我们期望的结果。

  代码如下:

public class Solution {
    private int Min(int num1, int num2, int num3){
        int n = num1 < num2 ? num1 : num2;
        int nn = n < num3 ? n : num3;
        return nn;
    }
    public int GetUglyNumber_Solution(int index) {
        if (index <= 0)
            return 0;
            
        int[] ugly = new int[index];
        ugly[0] = 1;
        int nextIndex = 1;
        int index2 = 0;
        int index3 = 0;
        int index5 = 0;
        
        while(nextIndex < index){
            int min = Min(ugly[index2] * 2, ugly[index3] * 3, ugly[index5] * 5);
            ugly[nextIndex] = min;

            while(ugly[index2] * 2 <= ugly[nextIndex])
                index2 ++;
            while(ugly[index3] * 3 <= ugly[nextIndex])
                index3 ++;
            while(ugly[index5] * 5 <= ugly[nextIndex])
                index5 ++;
            nextIndex += 1;
        }
        return ugly[nextIndex - 1];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值