剑指offer编程题解法汇总33-丑数

题目连接:

题目描述

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

数据范围:0≤n≤2000

要求:空间复杂度 O(n)O, 时间复杂度 O(n)

解题思路:

方案一:

首先一个简单方案,就是从1开始,一个一个的数去判断,但是这样会有性能问题,就是N=1500时输出值=859963392,则需要循环8E多次,效率太低。

方案二:

一个一个的找不行,那我们就换个思路,能不能通过2,3,5相互乘的组合来从小往大一个一个的找丑数。

丑数*2,*3,*5后一定还是丑数,那么根据这个,我们可以依次的从小到大找丑数。

三个变量i2,i3,i5用来记录
i2记录的是当前位置的丑数*2之后当前的最大值。记录的是i2位置的数乘以2之后参与比较的丑数。
i3,i5同理

我们的丑数数组是1,2,3,4,5,6,8,9,10,12...(从2开始的数组都是每轮运算加进来的)
我们可以这样比较,
第一轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于1*2,1*3,1*5比较,2最小,把2添加到丑数数组中,array[1]=2,则i2的位置由0变为1,此时array[i2]=2;

第二轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于2*2,1*3,1*5比较,3最小,把3添加到丑数数组中,array[2]=3,则i3的位置由0变为1,此时array[i3]=2;

第三轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于2*2,2*3,1*5比较,4最小,把4添加到丑数数组中,array[3]=4,则i2的位置由1变为2,此时array[i2]=3;

第四轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于2*4,2*3,1*5比较,5最小,把5添加到丑数数组中,array[4]=5,则i5的位置由0变为1,此时array[i5]=2;

第五轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于3*2,2*3,2*5比较,6最小,把6添加到丑数数组中,array[5]=6;,则i2的位置由2变为3,则i3的位置由1变为2,此时array[i2]=4,array[i3]=3;

第六轮:array[i2]*2,array[i3]*5,array[i5]*5比较,等于4*2,3*3,2*5比较,8最小,把8添加到丑数数组中,array[6]=8;,则i2的位置由3变为4,此时array[i2]=5;

继续第七轮,第八轮等等,每轮算出来的就是当前最小的丑数加入到数组当中。

代码

方案一代码:

 Set<Integer> set = new HashSet<>();
 //从小到大直接找
    public int GetUglyNumber_Solution(int index) {
        if (index <= 5) {
            return index;
        }
        set.add(1);
        set.add(2);
        set.add(3);
        set.add(4);
        set.add(5);
        int num = 5;
        int i = 6;
        while (num < index) {
            if (isChoushu(i)) {
                num++;
            }
            i++;
        }
        return --i;
    }

    private boolean isChoushu(int i) {
        if (i % 2 == 0) {
            if (set.contains(i / 2)) {
                set.add(i);
                return true;
            }
        }
        if (i % 3 == 0) {
            if (set.contains(i / 3)) {
                set.add(i);
                return true;
            }
        }
        if (i % 5 == 0) {
            if (set.contains(i / 5)) {
                set.add(i);
                return true;
            }
        }
        return false;
    }

方案二代码:

public int GetUglyNumber_Solution(int index) {
        int i = 0;
        int num2 = 0;
        int num3 = 0;
        int num5 = 0;
        int[] result = new int[index];
        result[0] = 1;

        while (i++ < index - 1) {
            int i2 = result[num2] * 2;
            int i3 = result[num3] * 3;
            int i5 = result[num5] * 5;
            int min = Math.min(Math.min(i2, i3), i5);
            result[i] = min;
            if (min == i2) {
                num2++;
            }
            if (min == i3) {
                num3++;
            }
            if (min == i5) {
                num5++;
            }
        }
        return result[index - 1];
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失落夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值